抽象数据类型Triplet的表示和实现
**定义**ADT ElemType{
数据对象:D = { e1,e2,e3|e1,e2,e3∈Elemset(定义了关系运算的某个集合) }
数据关系:R = {<e1,e2>,<e2,e3>}
}ADT ElemType
基本结构:
//------采用动态分配的顺序存储结构------//
typedef ElemType *Triplet; //由InitTriplet分配3个元素存储结构
//------基本操作的函数原型说明------//
Status InitTriplet (Triplet &T, ElemType v1, ElemType v2, ElemType v3);
//操作结果:构造三元组T,并为元素e1,e2,e3分别复赋参数v1,v2,v3的值
Status DestoryTriplet(Triplet &T);
//操作结果:三元组T被销毁
Status Get(Triplet &T,int i,ElemType &e);
//初始条件:三元组T已存在,1≤i≤3
//操作结果:用e返回三元组T中第i元的值
Status Put(Triplet &T,int i,ElemType &e);
//初始条件:
//操作结果:
…
//------基本操作的实现------//
Status InitTriplet (Triplet &T, ElemType v1, ElemType v2, ElemType v3){
T=(ElemType )malloc(3*sizeof(ElemType));
if(!T)
exit(OVERFLOW);//分配存储空间失败
T[0]=v1;
T[1]=v2;
T[2]=v3;
return OK;
}
Status DestoryTriplet(Triplet &T){
free(T);
T=NULL;
return OK;
}
Status Get(Triplet T, int i, ElemType &e) {
if(i<1||i>3)
return ERROR;
e=T[i-1];
return OK;
}
…
抽象数据类型-复数Complex
ADT Complex{
数据对象:D={r,i|r,i是实数}
数据关系:R={<r,i>|}
基本操作:
InitComplex(&C,r,i)
操作结果:构造一个复数C,实部为r,虚部为i
DestoryComplex(&C)
操作结果:销毁复数C
Get(&C,k,&e)
初始条件:C存在,且1<=k<=2;
操作结果 :用e返回C的第k元的值
Set(&C,k,e)
初始条件:C存在,且1<=k<=2;
操作结果:将C的第k元的值设置或改变为e
IsAscending(&C)
初始条件:C存在
操作结果:如果复数C的两个元素按照升序排列,则返回OK,否则返回ERROR
IsDescending(&C)
初始条件:C存在
操作结果:降序?
Max(&C,&e)
初始条件:C存在
操作结果:用e返回复数C中最大的元素
Min(&C,&e)
}ADT Complex
抽象数据类型:实数-RationalNumber
ADT RationalNumber{
数据对象:D = {s,m|s,m为有理数,且m不等于0} //分子,分母为实数且分母≠0
数据关系:R={<s,m>}
基本操作:
InitReationalNumber(&R,s,m)
操作结果:构造一个有理数,分子为s,分母为m
......
}
抽象数据类型:线性表
```css
ADT List{
数据对象:D={ ai|ai∈ElemSet,i=1,2...n,n≥0 }
数据关系:R={<ai-1,ai>|ai-1,ai∈D,i=1,2,...,n}
基本操作:
InitList(&L)
操作结果:构造一个空的线性表L
DestoryList(&L)
初始条件:线性表L已存在
操作结果:销毁线性表L
ClearList(&L)
初始条件:线性表L已存在
操作结果:将L重置为空表
ListEmpty(L)
初始条件:线性表L已存在
操作结果:若L为空表则返回TRUE,否则返回FALSE
ListLength(L)
初始条件:线性表L已存在
操作结果:返回L中数据元素个数
GetElem(L,i,&e)
初始条件:线性表L已存在
操作结果:用e返回L的第i个元素
LocateElem(L,e,compare())
初始条件:线性表L已存在,compare()是数据元素判定函数
操作结果:返回L中第1个与e满足关系compare()的数据元素的位序。若这样的数据元素不存在,则返回0
PriorElem(L,cur_e,&pre_e)
初始条件:线性表L已存在
操作结果:若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱 ,否则操作失败,则返回0
NextElem(L,cur_e,&next_e)
初始条件:线性表L已存在
操作结果:若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继,否则操作失败,next_e无定义
ListInsert(&L,i,e)
初始条件:线性表L已存在,1<=i<=ListLength(L)+1
操作结果:在L中第i个位置之前插入新的属于元素e,L的长度+1
ListDelete(&L,i,&e)
初始条件:线性表L已存在且非空,1<=i<=ListLength (L)
操作结果:删除线性表L的第i个数据元素,并用e返回其值,L长度-1
ListTraverse(L,vist())
初始条件:线性表L已存在
操作结果:依次对L的每个数据元素调用函数visit()。一旦visit()失败,则操作失败
}ADT List
归并应用
eg:已知两个线性表LA,LB,求A∪B 存放在LA中
方法:从线性表LB依次取数据元素,遍历LA,若LA中没有则插入。
```css
算法如下:
//将所有在Lb中但不在La中的元素插入到La中
void union(List &La,list Lb){
//求线性表长度
La_len=ListLength(La);
Lb_len=ListLength(Lb);
//在Lb中取元素
for(i=1;i<=Lb_len;i++){
GetElem(Lb,i,e);
if(!LocateElem(La,e,equal))
ListInsert(La,++La_len,e);
}
}//union
线性表的动态分布顺序存储结构
#define LIST_INIT_SIZE 100 //线性表存储空间的初始分配量
#define LISTINCRMENT 10 //线性表存储空间的分配增量
typedef struct{
ElemType *elem; //存储空间基址
int length; //当前长度
int listsize; //当前分配存储容量
}SqList;//顺序表
//构造一个空的线性表
Status InitList_Sq(&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;
}
/*
注意:数组是从0开始的,第i个元素 就是elem[i-1]
*/
//顺序表的插入操作
//在顺序表Sq的第i-1和i个位置中间插入元素e:需要将Sq的第i——n个元素后移 ,再将元素e插入到对应位置
//可在表头、表中、表尾插入元素
Status ListInsert_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,(LIST_INIT_SIZE + 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;
*p=e;//插入e
++L.length;//表长+1
return OK;
}
//顺序表的删除操作
//取出对应位置元素赋值给e,元素前移,表长-1
Status ListDelet_Sq(SqList &L,int i,ElemType &e) {
if(i<1||i>L.length)
return ERROR;
p = &(L.elem[i-1]);
e=*p;//取出第i个元素
q = L.elem+L.length-1;//表尾元素位置
for(p;p<q;p++)//该元素之后的元素往前移
*p = *(p+1);
--L.listsize;//表长-1
return OK;
}
归并线性表
**归并线性表**//线性表La和Lb中的数据元素按值非递减有序排列,合并La和Lb到Lc中,使得Lc中的数据元素也是非递减有序排列
void MergeList(List La,List Lb,List &Lc){
InitList(Lc);
i=j=1;
k=0;
La_len=ListLength(La);
Lb_List=ListLength(Lb);
while(i<=La_len&&j<=Lb_len){
GetElem(La,i,a);
GetElem(Lb,j,b);
if(a<=b)
ListInsert(Lc,++k,a);
else
ListInsert(Lc,++k,b);
}
while(i<=La_len)
ListInsert(Lc,++k,a);
while(j<=Lb_len)
ListInsert(Lc,++k,b);
} //MergeList
归并顺序表
void MergeList_Sq(SqList La,SqList Lb,SqList &Lc){
pa = La.elem;
pb = Lb.elem;
Lc.listsize = Lc.length = La.length + Lb.length;
pc = Lc.elem = (ElemType*)malloc(Lc.listsize*sizeof(ElemType));
if(!Lc.elem)
exit(OVERFLOW);//存储失败
pa_last = La.elem + La.length - 1;//pa最后一个元素地址
pb_last = Lb.elem + Lb.length -1;//pb最后一个元素地址
while(pa<=pa_last&&pb<=pb_last){
if(*pa<=*pb){
pc=pa;
pc++;
pa++
}//*pc++ = *pa++;
else{
pc=pb;
pc++;
pb++;
}//*pc++ = *pb++;
}
//插入剩余元素
while(pa<pa_last)
*pc++ = *pa++;
while(pb<pb_last)
*pc++ = *pb++;
}
**归并单链表 **
//La,Lb,Lc都为有头结点的单链表
用//pa,pb指向当前待插入的节点,pc指向最后一个节点
void MergeList_L(LinkList &La,LinkList &Lb,LinkList &Lc){
pa = La->next;//第1个节点
pb = Lb->next;
Lc = pc = La;//用La的头结点作为Lc的头结点
while(pa&&pb){
if(pa->data<=pb->data){
pc->next = pa;
pc=pa;
pa=pa->next;
}
else{
pc->next = pb;
pc=pb;
pb=pb->next;
}
}
pc->next = pa?pa:pb;//插入剩余段
free(Lb);//释放Lb的头结点
线性表的链式存储结构
//线性链表/单链表
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode, *LinkList;
//L为带头结点的单链表的头指针
Status GetElem_L(LinkList L,int i,ElemType &e){
p = L->next;//头结点
j = 1;
while(p&&j<i){//顺着指针向后查找,直到p指向第i个元素,或者p为空
p = p->next;
j++;
}
if(!p || j>i)
return ERROR;
e = p->data;//取第i个元素
return OK;
}
//L是带头结点的链表的指针,以e返回链表的第i个元素
Status GetElem_L(LinkList L,int i,ElemType &e){
p = L->next;//p指向第1个节点
j = 1;
while(p&&j<i){
p=p->next;
j++;
}
if(!p || j>i)
return ERROR;//第i个元素不存在
e = p->data;
return OK;
}
//将单链表重置为一个空表
void ClearList(&L){
while(L->next){
p=L->next;//p指向L的第1个节点
L->next = p->next;//删除p节点(也就是删除第1个结点)
free(p);
}
}
//单链表的插入操作
//在带头结点的单链线性表L的第 i个位置插入元素e:只需要修改指针
Status ListInsert_L(LinkList &L,int i,ElemType e){
p = L;
j = 0;
while(p&&j<i-1){//寻找第i-1个节点 -->p
p = p->next;
++j;
}
if(!p || j>i-1) //i>表长或者小于1
return ERROR;
newNode = (LinkList)malloc(sizeof(LNode));//生成新节点
newNode->data = e;
newNode->next = p->next;
p->next = newNode;//修改指针,插入结点
return OK;
}
//单链表的删除指定位置节点的操作
//删除带头结点的单链线性表L的第i个节点
Status ListDelete_L(LinkList &L,int i,ElemType &e){
p = L;//p指向头结点
j = 0;
while(p->next && j<i-1){
p=p->next;
j++;
}
//跳出循环时,p指向第j个节点,j=i-1
if(!p||j>i-1)//删除位置不合理
return ERROR;
q=p->next;
e=q->data;//将要删除的节点数据赋值给e
p->next = p->next->next;//删除结点
free(q);//释放结点
return OK;
}