2.3链表的补充
雙向鏈表:結點中有兩個指針域,其中一個指向后繼,一指向前驅
算法2.18:現在我們來看在雙向鏈表中插入一個結點
圖如下:
我們現在來看代碼:(書上代碼有錯誤,下面這個是我修改后的代碼)
Status ListInsert_Dul(DuLinkList &L,int i,ElemType e) {//在帶頭結點的雙鏈循環線性表L中第i個位置之前插入元素e//i的合法值為:1<=i<=表長+1DuLinkList p;p=L->next;if(!(p=GetElemP_Dul(L,i))) //在L中確定插入位置{return ERROR;}if(!(S=(DuLinkList)malloc(sizeof(DuLNode))))return ERROR;s->data=e;s->prior=p->prior;p->prior->next=s;s->next=p;p->prior=s;return OK; }現在我們來分析下:
1.這個Status指的是一種狀態,因為c語言不支持泛型。
2.這個GetElemP_Dul根據這套代碼,他返回了第i個節點的地址,把p指向了i指向的地址。
3.這里的ERROR和OK是一個宏(#define)
4.這個給S在堆區開辟空間,如果S為NULL,則ERROR
5.這里開始說明插入:
1.要插入的為S,先把s中data的值賦值為e。
2.把s的前驅先接好。
3.再把p的前驅的后繼接好。
4.隨后大家看代碼和圖,很簡單,自己操作時都會了(這里可能有些朋友會說我不記得這些順序怎么辦,其實可以不用記,自己敲一邊,就知道為什么順序了)
算法2.19:
下面我們來看刪除:
圖如下所示:
下面是書中代碼:
Status ListDelete_DuL(DuLinkList &L, int i, ElemType &e) {// 刪除帶頭結點的雙鏈循環線性表L的第i個元素,i的合法值為1≤i≤表長DuLinkList p;if (!(p = GetElemP_DuL(L, i))) // 在L中確定第i個元素的位置指針preturn ERROR; // p=NULL, 即第i個元素不存在e = p->data;p->prior->next = p->next;p->next->prior = p->prior;free(p); return OK; } // ListDelete_DuL下面我們來分析下:
1.這里面有個ElemType& e,這個東西呢我覺得在這里面有些畫蛇添足了,因為他釋放了這個空間但提取了他的值,可能在其他地方有用吧。
2.這里是先把p的后繼賦值給了p的前面那個節點的后繼,再把p的前驅賦值給p后繼的前驅,其實這個順序是無所謂的,當我們換了順序時,也沒有影響。
算法:2.20:
歸并La和Lb得到新的單鏈線性表Lc,Lc的元素也按值非遞減排列。
下面是書中的偽代碼:
Status MergeList_L(NLinkList &La, NLinkList &Lb, NLinkList &Lc, int (*compare)(ElemType, ElemType)) { // 已知單鏈線性表La和Lb的元素按值非遞減排列。// 歸并La和Lb得到新的單鏈線性表Lc,Lc的元素也按值非遞減排列。NLink ha, hb;Position pa, pb, q;ElemType a, b;if (!InitList(Lc)) return ERROR; // 存儲空間分配失敗ha = GetHead(La); // ha和hb分別指向La和Lb的頭結點hb = GetHead(Lb);pa = NextPos(La, ha); // pa和pb分別指向La和Lb中當前結點pb = NextPos(Lb, hb);while (pa && pb) { // La和Lb均非空a = GetCurElem(pa); // a和b為兩表中當前比較元素b = GetCurElem(pb);if ((*compare)(a, b)<=0) { // a≤bDelFirst(ha, q); Append(Lc, q); pa = NextPos(La, pa); } else { // a>bDelFirst(hb, q); Append(Lc, q); pb = NextPos(Lb, pb); }} // whileif (pa) Append(Lc, pa); // 鏈接La中剩余結點else Append(Lc, pb); // 鏈接Lb中剩余結點FreeNode(ha); FreeNode(hb); // 釋放La和Lb的頭結點return OK; } // MergeList_L這里我就只能說下思路了,因為這里很多函數都被寫好了。并且書里面也沒給出具體代碼,所以在此只能給大家分析下思路,這個程函數前三個參數分別是La,Lb,Lc鏈表的引用,從代碼上看,La,Lb都是有數據的,Lc是空的(因為pa=NextPos(La,ha)和pb=NextPos(Lb,hb))。第三個參數就是一個比較。這個initList函數顧名思義就是初始化鏈表,GetHead函數就是獲得線性鏈表的頭結點地址,這個NextPos里面有兩個參數,第一個是鏈表,第二個是節點,這個函數的意思就是得到指定節點的后繼結點的位置。
程序的整體思路是:比較La,Lb中的元素依次比較(都是非遞減的),比較完后,最后剩下的那個鏈直接用Append進行附加。
總結
- 上一篇: C/C++屏幕恶搞程序
- 下一篇: 丘成桐中学计算机科学奖,丘成桐中学科学奖