赞
踩
ADT List{
数据对象:
D={ai|ai∈ElemSet,i=1,2,...n,n>=0}
称n为线性表的表长,称n=0时的线性表为空表
数据关系:
R1={<ai-1,ai>|ai-1,ai∈D,i=2,...,n}
{ 设线性表为(a1,a2,...,ai,....,an}称i为ai在线性表中的位序}
本操作:
结构初始化操作
结构销毁操作
引用型操作
销毁操作
}ADT;
(1)结构初始化操作 InitList(&L) (2)结构销毁操作 DestroyList(&L) (3)引用型操作 ListEmpty(L) (线性表判空) ListLength(L) (求线性表的长度) PriorElem(L,cur_e,&pre_e)(求数据元素的前驱) NextElem(L,cur_e,&next_e)(求数据元素的后继) GetElem(L,i,&e)(求线性表某个数据元素,返回线性表中第i个元素的值) LocateElem(L,e,compare()) (定位函数,返回L中第一个与e相等的位序) ListTraverse(L,visit())(遍历线性表,初始条件是线性表L存在) (4)结构初始化操作 ClearList(&L)(线性表置空) PutElem(&L,i,e)(将e的值赋给第i个元素) ListInsert(&L,i,e)(插入数据元素,在第i个元素前插入新的元素e,L的长度增1) ListDelete(&L,i,&e)(删除L的第i个元素,并用e返回其值,L的长度减1)
假设有两个集合A和B分别用两个线性表LA和LB表示,即线性表中的数据元素即为集合中的成员,现在求
一个新的集合,要求
A=A∪B
A={1,2,4,6,7}
B={1,3,9,8}
操作步骤:
⭐️ 合并两个数组
void union(List &la,List lb){
la_len=listlength(la);
lb_len=listlength(lb);
for(i=1;i<lb_len;i++){
GetElem(lb,i,e);
if(!LocateElem(la,e,equal()))
ListInsert(la,++la_len,e);
}
}
已知一个非纯集合B,试构造一个纯集合A,使A 中只包含B中所有各不相同的数据元素
初始:A={ },B={6,2,9,3,6}
结果: A={6,2,9,3}
上述问题可以演绎为:
将存在于集合B中的元素逐个放入空集合A中,但A中不能有重复元素,算法策略与例1相同。
⭐️ 过滤集合中的重复元素
void union(List&la,list lb){
InitList(la);
la_len=ListLength(la);
lb_len=listlength(lb);
for(i=1;i<=lb_len;i++){
GetElem(lb,i,e);
if(!LocateElem(la,e,equal()))
ListInsert(la,++la_len,e);
}
}
有序表
若线性表中的数据元素相互之间可以比较,并且数据元素在线性表中依值非递减或者非递增有序排列,
则称改线性表为有序表(Ordered List)
A={1,4,5,7,9,12,15,17,20}
B={2,3,6,6,8}
C=A∪B={1,2,3,4,5,6,6,7,8,9,12,151,7,20}
⭐️ 合并两个有序数组
void MergeList(List la,List lb,List&lc){ //本算法将非递减的有序表la和lb归并为lc InitList(LC);//构造空的线性表lc i=j=1; k=0; la_len=listlength(la); lb_le=listlength(lb); while((i<=la_len)&&(j<=lb_len)){//la和lb均不为空 //la和lb均不为空 GetElem(la,i,ai); GetElem(lb,j,bj); if(ai<=bj){ ListInsert(lc,++k,ai);//将ai插入到lc中 ++i; } eles{ ListInsert(lc,++k,bj);//将bj插入到lc中 ++j; } } while(i<=la_len){//当la不为空时 GetElem(la,i++,ai); ListInsert(lc,++k,ai); }//插入la表中的剩余元素 while(j<=lb_len){//当lb不为空时 GetElem(lb,++j,bj); ListInsert(lc,++k,bj); }//插入lb表中的剩余元素 }
length
: 当前元素个数(当前已经占用的存储空间的大小)
listsize
: 当前分配的存储空间大小
ElemType *elem
: 指向存储空间的基地址
#define LIST_INIT_SIZE 100 //线性表存储空间的初始分配量 #define LISTINCREMENT 10 //线性表存储空间的分配增量 typedef struct{ ElemType *elem; //存储空间基址 int length;//当前长度 int listsize;//当前分配的存储容量 }SqList; //称为 顺序表 //顺序表的初始化 Status InitList_Sq(SqList& L){ L.elem=(ElemType*)malloc(LIST_init_SIZE*sizeof(ElemType)); if(!L.elem)exit(OVERFLOW); L.length=0; L.listsize=LIST_INIT_SIZE; return OK; }//Init_Sq //算法时间复杂度O(1)
int LocateElem_Sq(SqList L,ElemType e,Status (*compare)(ElemType,ElemType)){
//在顺序表中查询第一个满足判定条件的数据元素
//若存在,则返回它的位序,否则返回0
i=1; //i 的初值为第1元素的位序
p=L.elem;
while(i<=L.length&&!(*compare)(*p++,e))
++i;
if(i<=L.length)
return i;
else
return 0;
}//LocateElem_Sq
//算法时间复杂度O(ListLength(L)
typedef struct{
int *elem;//存储空间基址
int length;//当前长度
int listsize; //当前分配的存储容量,以sizeof(ElemType)为单位
}SqList; //称为顺序表
L.elem=(int*)malloc(LIST_INIT_SIZE*sizeof(int));
// 第一个元素a0: L->elem[0]
//第i个元素ai: L->elem[i-1]
//第n个元素an: L->elem[n-1] 或者L->elem[L->length-1]
Status LisInsert_Sq(SqList&L,int i,ElemType e){ if(i<1||i>L.length+1) return ERROR; //插入位置不合法 if(L.length>=L.listsize){//分配存储空间 newbase=(ElemType *)realloc(L.elem, (L.listsize+LISTINCREMENT)*sizeof(ElemType)); if(!newbase) exit(OVERFLOW); L.elem=newbase; L.listsize+=LISTINCREMENT; } q=&(L.elem[i-1]);//q指示插入位置 for(p=&(L.elem[L.length-1]);p>=q;--p) *(p+1)=*p; //插入位置及之后位置向后移位 *q=e; //插入e ++L.length; //表长增1 return OK } //时间性能 若在线性表中任何一个位置上进行插入的概率都是相等的,则移动元素的期望值为: n/2
q=&(L.elem[i-1]);
*(p+1)=*p;
Status ListDelete_Sq(SqList &L,int i,ElemType &e){
if((i<1)||(i>L.length))
return ERROR;//删除位置不合法
p=&(L.elem[i-1]);// p为被删除元素的位置
e=*p; //被删除元素的值赋给e
q=L.elem+L.length-1; //表尾元素的位置
for(++p;p<=q;++p)
*(p-1)=*p;//被删除元素之后的元素左移
--L.length;//表长减1
return OK
}
//删除算法的时间性能
// E=qi(n-i) 求和(i-1到n)
//若假定在线性表中任何一个位置上进行删除的元素概率相等 则 E=n-1/2
q=&(L.elem[n-1]);
//或
q=L.elem+L.length-1;
*(p-1)=*p;
用一组地址任意的存储单元存放线性表中的数据元素
结点和单链表的类C语言描述
Typedef struct LNode{
ElemType data; //数据域
struct LNode *next //指针域
}LNode,*LinkList;
LinkList L; //L为单链表的头指针
生成链表的过程是结点逐个插入的过程
⭐️ 头插法生成链表
void CreateList_L(LinkList& L,int n){
//逆序输入n个数据元素,建立带头结点的单链表
L=(LinkList)malloc(sizeof(LNode));
L->next=NULL; //先建立一个带头结点的单链表
for(i=n;i>0;--i){
p=(LinkList)malloc(sizeof(LNode));
scanf(&p->data); //输入元素值
p->next=L->next;
L->next=p; //插入
}
}//插入
Status GetElem(LinkList L,int i,ElemType &e){
p=L->next;
j=1;
while(p&&j<i){
p=p->next;
++j;
}
if(!p||j>i)
return ERROR;//第i个元素不存在
e=p->data; //取得第i个元素
return OK;
}
//算法时间复杂度 O(n) n为单链表的长度
typedef struct LNode{
ElemType data;
struct LNode *next;
}*Link,*Position;
typedef struct{
Link head,tail;//分别指向头结点和最后一个结点的指针
int len;//指示链表长度
Link current;//指向当前被访问的结点的指针,初始位置指向头结点
}LinkList;
L->next;
p->next->next;
Status ListInsert_L(LinkList L,int i,ElemType e){ //本算法在链表中第i个结点之前插入新的元素e p=L; j=0; while(p&&j<i-1){ p=p->next; ++j; //寻找第i-1个结点 } if(!p||j>i-1) return ERROR; //i大于表长或者小于1 S=(LinkList)malloc(sizeof(LNode)); //生成新结点 s->data=e; s->next=p->next; p->next=s; //插入 } //算法时间复杂度 O(n)
s=(LinkList)malloc(sizeof(LNode));
s->data=m;
s->next=p->next;
p->next=s;
p=s;
s=(LinkList)malloc(sizeof(LNode));
s->data=n;
s->next=p->next;
p->next=s;
// 将链表第i个元素删除 Status ListDelte(LinkList L,int i,Elmetype &e){ p=L; j=0; while(p->next&&j<i-1){ p=p->next; ++j; } if(!(p->next)||j>i-1) return ERROR; q=p->next; p->next=q->next; e=q->data; free(q); return OK; } //清空链表 void ClearList(&L){ while(L->next){ p=L->next; L->next=p->next; free(p); } }
q=p->next;
p->next=q->next;
free(q);
q=p->next;
p->next=q->next;
free(q);
最后一个结点的指针域的指针又指回头结点的链表
判别链表最后一个结点的条件是: 后继结点是否指向头结点
Typedef struct LNode{ ElemType data; //数据域 struct LNode *next //指针域 }LNode,*LinkList; void CreatList(LinkList L,int n){ int i; Lnode *p,*s; p=L; for(i=1;i<n;i++){ s=(LinkList)malloc(sizeof(LNode)); s->data=i+1; s->next=p->next; p->next=s; p=s; } }
typedef struct DuLNode{ ElemType data; //数据域 struct DuLNode *prior; //指向前驱的指针域 struct DuLNode *next; //指向后继的指针域 }DuLNode, *DuLinkList; void CreatListHead(DuLinkList L,int n){ int i; LNode *p,*s; p=L; for(int i=0;i<n;i++){ printf("请输入第%d个元素:",i+1); s=(DuLinkList)malloc(sizeof(LNode)); scanf("%d",&s->data); s->next=p->next; s->prior=p; p->next=s; if(s->next) s->next->prior=s; } }
s->next=p->next;
p-next=s;
s->next->prior=s;
s->prior=p;
在双向链表中的元素ai前插入一个新元素e,指针p指向结点ai,写出相应的算法语句
s=(DuLinkList)malloc(sizeof(DulNode));
s->data=e;
s->prior=p->prior;
p->prior->next=s;
s->next=p;
p->prior=s;
q =p->next
p->next=p->next->next;
q->next->prior=p;
free(q);
e=p->data;
p->prior->next=p->next;
p->next->prior=p->prior;
free(p);
Status Contrary(LinkList &L){
t=L; //t指向单循环链表的头结点
p=t->next; //p指向单循环链表的第一个结点
q=p->next; //q指向单循环链表的第二个结点
while(p!=L){
p->next=t; //让p结点next域指针指向其前驱
t=p; //顺链向后移动指针t
p=q; //顺链向后移动指针p
q=p->next; //顺链向后移动指针q
}
L->next=t; //让L的next域指针指向新链表的第一个结点
return OK;
}
void LinkListDelete(LinkList L,int n,int m) {//依次删除不带头结点单循环链表的第m个元素 LNode *p,*s; int i,j; p=L; for(i=0;i<n;i++) { j=1; while(j<m-1)//直到p指向第m-1个元素 { p=p->next; j++; } s=p->next;//s指向第m个元素,删除该结点 p->next=s->next; printf("%d",s->data); free(s); p=p->next; } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。