帶頭結點的單鏈表的12個基本操作

前面說了帶頭結點與不帶頭結點這兩種單鏈表的一些情況,同時我們知道設置了頭結點的單鏈表可以降低程序複雜性與減少BUG出現率,那麼接下來我們來探討一下關於帶頭結點的單鏈表的一些基本操作,這很重要。

線性表的單鏈表存儲結構定義如下:

1 struct LNode
2 {
3     ElemType data;
4     LNode *next;
5 };
6 typedef LNode *LinkList; // 另一種定義LinkList的方法

以下是帶有頭結點的單鏈表的12個基本操作:

001 void InitList(LinkList &L)
002 { // 操作結果:構造一個空的線性表L
003   L=(LinkList)malloc(sizeof(LNode)); // 產生頭結點,並使L指向此頭結點
004   if(!L) // 存儲分配失敗
005     exit(OVERFLOW);
006   L->next=NULL; // 頭結點的指針域爲空
007 }
008  
009 void DestroyList(LinkList &L)
010 { // 初始條件:線性表L已存在。操作結果:銷燬線性表L
011   LinkList q;
012   while(L) // L指向結點(非空)
013   { q=L->next; // q指向首元結點
014     free(L); // 釋放頭結點
015     L=q; // L指向原首元結點,現頭結點
016   }
017 }
018  
019 void ClearList(LinkList L) // 不改變L
020 { // 初始條件:線性表L已存在。操作結果:將L重置爲空表
021   LinkList p=L->next; // p指向第1個結點
022   L->next=NULL; // 頭結點指針域爲空
023   DestroyList(p); // 銷燬p所指的單鏈表
024 }
025  
026 Status ListEmpty(LinkList L)
027 { // 初始條件:線性表L已存在。操作結果:若L爲空表,則返回TRUE,否則返回FALSE
028   if(L->next) // 非空
029     return FALSE;
030   else
031     return TRUE;
032 }
033  
034 int ListLength(LinkList L)
035 { // 初始條件:線性表L已存在。操作結果:返回L中數據元素的個數
036   int i=0; // 計數器初值爲0
037   LinkList p=L->next; // p指向第1個結點
038   while(p) // 未到表尾
039   { i++; // 計數器+1
040     p=p->next; // p指向下一個結點
041   }
042   return i;
043 }
044  
045 Status GetElem(LinkList L,int i,ElemType &e) // 算法2.8
046 { // L爲帶頭結點的單鏈表的頭指針。當第i個元素存在時,其值賦給e並返回OK;否則返回ERROR
047   int j=1; // 計數器初值爲1
048   LinkList p=L->next; // p指向第1個結點
049   while(p&&j<i) // 順指針向後查找,直到p指向第i個結點或p爲空(第i個結點不存在)
050   { j++; // 計數器+1
051     p=p->next; // p指向下一個結點
052   }
053   if(!p||j>i) // 第i個結點不存在
054     return ERROR;
055   e=p->data; // 取第i個元素的值賦給e
056   return OK;
057 }
058  
059 int LocateElem(LinkList L,ElemType e,Status(*compare)(ElemType,ElemType))
060 { // 初始條件:線性表L已存在,compare()是數據元素判定函數(滿足爲1,否則爲0)
061   // 操作結果:返回L中第1個與e滿足關係compare()的數據元素的位序。
062   //           若這樣的數據元素不存在,則返回值爲0
063   int i=0; // 計數器初值爲0
064   LinkList p=L->next; // p指向第1個結點
065   while(p) // 未到表尾
066   { i++; // 計數器+1
067     if(compare(p->data,e)) // 找到這樣的數據元素
068       return i; // 返回其位序
069     p=p->next; // p指向下一個結點
070   }
071   return 0; // 滿足關係的數據元素不存在
072 }
073  
074 Status PriorElem(LinkList L,ElemType cur_e,ElemType &pre_e)
075 { // 初始條件:線性表L已存在
076   // 操作結果:若cur_e是L的數據元素,且不是第一個,則用pre_e返回它的前驅,返回OK,
077   //           否則操作失敗,pre_e無定義,返回ERROR
078   LinkList q,p=L->next; // p指向第1個結點
079   while(p->next) // p所指結點有後繼
080   { q=p->next; // q指向p的後繼
081     if(q->data==cur_e) // p的後繼爲cur_e
082     { pre_e=p->data; // 將p所指元素的值賦給pre_e
083       return OK; // 成功返回OK
084     }
085     p=q; // p的後繼不爲cur_e,p向後移
086   }
087   return ERROR; // 操作失敗,返回ERROR
088 }
089  
090 Status NextElem(LinkList L,ElemType cur_e,ElemType &next_e)
091 { // 初始條件:線性表L已存在
092   // 操作結果:若cur_e是L的數據元素,且不是最後一個,則用next_e返回它的後繼,返回OK,
093   //           否則操作失敗,next_e無定義,返回ERROR
094   LinkList p=L->next; // p指向第1個結點
095   while(p->next) // p所指結點有後繼
096   { if(p->data==cur_e) // p所指結點的值爲cur_e
097     { next_e=p->next->data; // 將p所指結點的後繼結點的值賦給next_e
098       return OK; // 成功返回OK
099     }
100     p=p->next; // p指向下一個結點
101   }
102   return ERROR; // 操作失敗,返回ERROR
103 }
104  
105 Status ListInsert(LinkList L,int i,ElemType e) // 算法2.9。不改變L
106 { // 在帶頭結點的單鏈線性表L中第i個位置之前插入元素e
107   int j=0; // 計數器初值爲0
108   LinkList s,p=L; // p指向頭結點
109   while(p&&j<i-1) // 尋找第i-1個結點
110   { j++; // 計數器+1
111     p=p->next; // p指向下一個結點
112   }
113   if(!p||j>i-1) // i小於1或者大於表長
114     return ERROR; // 插入失敗
115   s=(LinkList)malloc(sizeof(LNode)); // 生成新結點,以下將其插入L中
116   s->data=e; // 將e賦給新結點
117   s->next=p->next; // 新結點指向原第i個結點
118   p->next=s; // 原第i-1個結點指向新結點
119   return OK; // 插入成功
120 }
121  
122 Status ListDelete(LinkList L,int i,ElemType &e) // 算法2.10。不改變L
123 { // 在帶頭結點的單鏈線性表L中,刪除第i個元素,並由e返回其值
124   int j=0; // 計數器初值爲0
125   LinkList q,p=L; // p指向頭結點
126   while(p->next&&j<i-1) // 尋找第i個結點,並令p指向其前驅
127   { j++; // 計數器+1
128     p=p->next; // p指向下一個結點
129   }
130   if(!p->next||j>i-1) // 刪除位置不合理
131     return ERROR; // 刪除失敗
132   q=p->next; // q指向待刪除結點
133   p->next=q->next; // 待刪結點的前驅指向待刪結點的後繼
134   e=q->data; // 將待刪結點的值賦給e
135   free(q); // 釋放待刪結點
136   return OK; // 刪除成功
137 }
138  
139 void ListTraverse(LinkList L,void(*visit)(ElemType))
140 // visit的形參類型爲ElemType,與bo2-1.cpp中相應函數的形參類型ElemType&不同
141 { // 初始條件:線性表L已存在。操作結果:依次對L的每個數據元素調用函數visit()
142   LinkList p=L->next; // p指向第1個結點
143   while(p) // p所指結點存在
144   { visit(p->data); // 對p所指結點調用函數visit()
145     p=p->next; // p指向下一個結點
146   }
147   printf("\n");
148 }
發佈了18 篇原創文章 · 獲贊 4 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章