循环链表 循环链表的合并 1 2 3 4 5 6 7 LinkList Connect (LinkList Ta,LinkList Tb) { Nnode* p = Ta -> next; Ta -> next = Tb -> next -> next; free (Tb -> next); Tb -> next = p; return Tb; }
双向链表 双向链表的定义 1 2 3 4 5 typedef struct DuLNode { Elemtype data; struct DuLNode * prior; struct DLNode * next; }DuLNode,*DuLinkList;
双向链表的插入 1 2 3 4 5 6 7 8 9 10 11 int ListInsert_Dul (DuLinkList &L,int i,ElemType e) { if (!(p=GetElemP_Dul (L,i))) return 0 ; DuLNode* s = (DuLNode*)malloc (sizeof (DuLNode)); s -> data = e; s -> prior = p -> prior; s -> next = p; (p -> prior) -> next = s; p -> prior = s; return 1 ; }
双向链表的删除 1 2 3 4 5 6 7 8 int ListDelete_DuL (DuLinkList &L,int i,ElemType &e) { if (!(p=GetElemP_Dul (L,i))) return 0 ; e = p -> data; (p -> next) -> prior = p -> prior; (p -> prior) -> next = p -> next; free (p); return 1 ; }
单链表、循环链表和双向链表的时间效率比较
查找表头结点(首元结点)
查找表尾结点
查找结点*P的前驱结点
带头结点的单链表 L
L -> next 时间复杂度O(1)
从L -> next依次向后遍历 时间复杂度O(n)
通过p -> next无法找到其前驱
带头结点的仅设头指针L 的循环 单链表
L -> next 时间复杂度O(1)
从L -> next依次向后遍历 时间复杂度O(n)
通过p -> next可以找到其前驱 时间复杂度O(n)
带头结点的仅设尾指针R 的循环 单链表
R -> next -> next 时间复杂度O(1)
R 时间复杂度O(1)
通过p -> next可以找到其前驱 时间复杂度O(n)
带头结点的双向循环 链表L
L -> next 时间复杂度O(1)
L -> prior 时间复杂度O(1)
通过p -> prior 时间复杂度O(1)
顺序表和链表的比较 链表的优缺点 优点:
结点空间可以动态申请和释放
插入和删除时不需要移动数据元素
缺点:
存储密度小,每个结点的指针域会占用额外的存储空间
$存储密度 = \frac{结点数据本身占用的空间}{结点占用的空间总量}$(即$\frac{数据域所占空间}{数据域所占空间+指针域所占空间}$)(顺序表的存储密度为1)
链式存储结构是非随机存取 结构,对任一结点的操作都要从头指针依指针链查找到该节点
适用情况
表长变化较大
频繁进行插入或删除操作
顺序表的优缺点 优点:
存储密度为1,不用为表示结点间逻辑结构增加而外的存储开销
随机存取 ,按位置访问元素的时间复杂度为O(1)
缺点:
结点空间预先分配,可能会导致闲置或溢出
插入和删除时平均约移动表中一半元素,时间复杂度O(n)
适用情况
表长变化不大,且能事先确定变化范围
很少进行插入或删除操作,经常按元素位置序号访问数据元素
线性表的应用 线性表的合并(将Lb表插入到La表后) 1 2 3 4 5 6 7 8 9 void union (List &La,List &Lb) { La_Len = ListLength (La); Lb_Len = ListLength (Lb); for (i = 1 ,i <= Lb_Len.i++){ GetElem (i,Lb,e); if (!LocateElem (La,e)) ListInsert (&La,e,La_Len++); } }
算法的时间复杂度为: O(ListLength(La) * ListLength(Lb))
有序表的合并(顺序表实现) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 void MergeList_Sq (SqList LA,SqList LB,SqList &LC) { int * pa = LA.elem; int * pb = LB.elem; LC.length = LA.length + LB.length; LC.elem = (int *)malloc (sizeof (int ) *max_Size); int * pc = LC.elem; int * pa_Last = LA.elem + LA.lenght - 1 ; int * pb_Last = LB.elem + LB.lenght - 1 ; while (pa <= pa_Last && pb <= pb_Last){ if (*pa >= *pb) *pc++ = *pb++; else *pc++ = *pa++; } while (pa <= pa_Last)*pc++ = *pa++; while (pa <= pa_Last)*pc++ = *pb++; }
有序表的合并(链表实现) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 void MergeList_L (LinkList LA,LinkList LB,LinkList &LC) { LNode* p = LA -> next;LNode* q = LB -> next; LNode* r = LC = LA; while (p != NULL && q != NULL ){ if (p -> data >= q -> data){ r -> next = q; r = q; q = q -> next; } else { r -> next = p; r = p; p = p -> next; } r -> next = p ? p : q; free (LB); } }
综合应用案例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 typedef struct PNode {float coef; int expn; struct PNode * next; }PNode,*Polynomal; typedef struct PNode {float coef; int expn; struct PNode * next; }PNode,*Polynomal; void MergeList_L (Polynomal LA,Polynomal LB,Polynomal &LC) { PNode* p = LA -> next;PNode* q = LB -> next; PNode* r = LC; while (p != NULL && q != NULL ){ if (p -> expn == q -> expn){ if (p -> coef + q -> coef == 0 ){ p = p -> next; q = q -> next; continue ; } else { PNode* s = (PNode*)malloc (sizeof (PNode)); s -> next = NULL ; s -> coef = p -> coef + q -> coef; s -> expn = p -> expn; r -> next = s; r = r -> next; p = p -> next; q = q -> next; } } else if (p -> expn < q -> expn){ r -> next = p; p = p -> next; r = r -> next; } else { r -> next = q; q = q -> next; r = r -> next; } } r -> next = p ? p : q; }