04_006 |
Status ListInsert_L(LinkList L, int pos, ElemType e) { p = L; j = 0; while(p && j < pos-1) { p = p->next; ++j; //寻找第pos-1个结点 if(!p || j > pos-1) return ERROR; // pos小于1或者大雨表长 s = (LinkList) malloc(sizeof(LNode)); //生成新结点 s->data = e; s->next = p->next; //插入L中 p->next = s; return OK; } } //LinstInsert_L |
算法的时间复杂度为:O(ListLength(L))
现象表的操作ListDelete(&L,i,&e)在链表中的实现:
基本操作为:找到线性表中第i-1个结点,修改其指向后继的指针有序对<ai-1,ai>和<ai,ai+1>改变为<ai-1,ai+1>
04_007 |
Status ListDelete_L(LinkList L, int pos, ElemType &e) { p = L; j = 0; while(p->next && j < pos) { p = p->next; ++ j; //寻找第pos个结点,并令p指向其前驱 } if(!(p->next) || j > pos-1) return ERROR; //删除位置不合理 q = p->next; p->next = q->next; //删除并释放结点 e = q->data; free(q); return OK; } //ListDelete_L |
算法的时间复杂度为:O(ListLength(L))
05_001 |
void CreateList_L(LinkList &L, int 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; //插入到表头 } } // CreateList_L |
算法的时间复杂度为:O(ListLength(L))
05_002 |
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) } } //union |
上述算法的时间复杂度:
控制结构:for循环
基本操作:LocateElem(La,e,equal())
当以顺序映像实现抽象数据类型线性表时为:)
当以链表映像实现抽象数据类型线性表时为:
05_003 |
void purge(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(! equal(en, e)) { ListInsert(La, ++La_len, e); en = e; } } } |
上述算法的时间复杂度:
控制结构:for循环
基本操作:GetElem(Lb, i, e)
当以顺序映像实现抽象数据类型线性表时为:
当以链表映像实现抽象数据类型线性表时为:
05_004 |
void MergeList(List La, List Lb, List & Lc) { InitList(Lc); i = j = 1; k = 0; La_len = ListLength(La); Lb_len = ListLength(Lb); while((i <= La_len) && (j <= Lb_len)) { GetElem(La, i, ai); GetElem(Lb, j, bj); if(ai <= bj) { ListInsert(Lc, ++ k, ai); ++ i; } else { ListInsert(Lc, ++ k, bj); ++ j; } } } |
上述算法的时间复杂度:
控制结构:三个并列的while循环
基本操作:ListInsert(Lc, ++ k, bj);
当以顺序映像实现抽象数据类型线性表时为:
当以链表映像实现抽象数据类型线性表时为:
用上述定义的单链表实现线性表的操作时,存在的问题:
1. 单链表的表长是一个隐含的值;
2. 在单链表中的最后一个元素后插入元素时,需遍历整个链表;
3. 在链表中,元素的“位序”概念淡化,结点的“位置”概念强化。
改进链表的设置:
1. 增加“表长”,“表尾指针”和“当前位置的指针”三个数据域;
2. 将基本操作由位序“改为指针”
四、一个带头结点的线性表类型
05_005 |
typedef struct LNode { //结点类型 ElemType data; struct LNode *next; } *Link, *Position; |
Status MakeNode(Link &p, ElemType e);//分配由p指向的值为e的结点,并返回OK;
//若分配失败,则返回ERROR
void FreeNode(Line &p); //释放p所指结点
05_006 |
typedef struct {//链表类型 Link head, tail; //指向头结点和最后一个结点 int len; //指示链表长度 Link current; //指向当前访问的结点的指针, //初始位置指向头结点 } LinkList; |
链表的基本操作:
{结构初始化和销毁结构}
Status InitList(LinkList &L); //构造一个空线性链表L
//头指针、尾指针和当前指针均指向头结点,表长为零
Status DestoryList(LinkList &L); //销毁线性表L,L不再存在
{引用类型}
Status ListEmpty(LinkList L); //叛表空
Int ListLength(LinkList L); //求表长
Status Prior(LinkList L);//改变当前指针指向其前驱
Status Next(LinkList L);//改变当前指针指向后继
ElemType GetCurElem(LinkList L); //返回当前指针所指数据元素
Status LocatePos(LinkList L, int i); //改变当前指针指向第i个结点
Status LocateElem(LinkList L, ElemTypee,Status(* compare)(ElemType, ElemType));
//若存在与e满足函数compare()判定关系的元素,则移动当前指针
//指向第1个满足条件的元素,并返回OK;否则返回ERROR
Status ListTraverse(LinkList L,Status(*visit)()); //依次对L的每个元素调用函数visit()
{加工型操作}
Status ClearList(LinkList & L);//重置为空表
Status SetCurElem(LinkList & L,ElemType e); //更新当前指针所指数据元素
Status Append(LinkList & L, Link s); //一串结点链接在最后一个结点之后
Status InsAfter(LinkList & L, ElemTypee); //将元素e插入在当前指针之后
Status DelAfter(LinkList & L, ElemType*e); //删除当前指针之后的结点
05_007 |
Status InsAfter(LinkList & L, ElemType e) { //若当前指针在链表中,则将数据元素e插入在线性表L中 //当前指针所指结点之后,则返回OK;否则返回ERROR if(! L.current) return ERROR; if(! MakeNode(s, e)) return ERROR; s->next = L.current->next; L.current->next = s; return 0K; } // InsAfter |
05_008 |
Status DelAfter(LinkList & L, ElemType & e) { //若当前指针及其后继在链表中,则删除线性表L中当前指针 //所指结点之后的结点,并返回OK,否则返回ERROR if( !(L.current && L.current->next)) return ERROR; q = L.current->next; L.current->next = q->next; e = q->data; FreeNode(q); return OK; } // DelAfter |
{利用上述定义的线性表可以完成线性表的其它操作}
例一:
05_009 |
Status ListInsert_L(LinkList L, int i, ElemType e) { //带头结点的单链线性表L的第i个元素之前插入元素e if(! LocatePos(L, i-1)) return ERROR; //插入在第i-1个结点之后 else return ERROR; } // ListInsert_L |
05_010 |
void MergeList_L(LinkList & La, LinkList & Lb, LinkList & Lc, int(*compare)(ElemType, ElemType))) { if(! InitList(Lc)) return ERROR; //存储空间分配失败 LocatePos(La, 0); LocatePos(Lb, 0); //当前指针指向头结点 if(DelAfter(La, e)) a = e; else a = MAXC; //MAXC为常量最大值 while(! (a = MAXC && b = MAXC)) { //La或Lb非空 ... } DestoryList(La); DestoryList(Lb); //销毁链表La和Lb return OK; } // MergeList_L
if((*compare)(a, b) <= 0) { // a <= b InsAfter(Lc, a); if(DelAfter(La, el) a = el; else a = MAXC; } else { // a > b InsAfter(Lc,s); if(DelAfter(Lb, e) b = el; else b = MAXC } |