1. 熟悉什麼是鍊錶,鍊錶的分類?
鍊錶是一種物理儲存結構上非連續,非順序的儲存結構,資料元素的邏輯順序是通過鍊錶中的指標鏈結次序實現的。
鍊錶一共分為8種。1.單向、雙向。2.帶頭、不帶頭。3.迴圈、不迴圈。由這幾種情況組合而成。
常見的是不帶頭非迴圈單鏈表、帶頭迴圈雙向鍊錶。
2. 熟悉鍊錶帶頭結點和不帶頭結點的區別?頭指標:通常使用「頭指標」來標識乙個鍊錶,如單鏈表l,頭指標為null的時表示乙個空鍊錶。
頭結點:在單鏈表的第乙個結點之前附加乙個結點,稱為頭結點。頭結點的data域可以不設任何資訊,也可以記錄表長等相關資訊。
[注意]無論是否有頭結點,頭指標始終指向鍊錶的第乙個結點。如果有頭結點,頭指標就指向頭結點。
引入頭結點的優勢
鍊錶可以沒有頭結點,但是必須要有頭指標,因為要用頭指標來標識乙個鍊錶。設煉表的頭指標為phead。除了頭結點之外,還需要乙個指向鍊錶一般元素的指標pnode(因為phead只能指向表頭,不能指向其他元素,故需要另設指標)。
優勢1:第1個位置的插入刪除更加方便
若使用頭結點,則第1個位置的插入和刪除都是對p—>next進行操作,而不用動p本身,而且減少了演算法分支(即if else分支)具體的流程為:
插入操作如下
1.p指向要插入結點的前驅結點,若要插入的結點為第1個位置,則其前驅結點就是頭結點,此時p指向頭結點。
2.讓新結點s的next指向p的next,即s—>next = p—>next;
3.讓p—>next指向s,即p—>next = s;
刪除操作如下
1.p指向要刪除結點的前驅結點,若要刪除的結點為第1個位置,則其前驅結點就是頭結點,此時p指向頭結點。
2.讓臨時指標q指向要刪除的結點,即q = p—>next;
3.讓p的next指向要刪除結點的下乙個結點,即p—>next = q—>next;
4.釋放q的空間,即free(q);
若沒有頭結點,在第1個位置插入或刪除時,需要動頭指標。
插入操作如下
1.判斷要插入的是否是第1個位置,若是需要特殊處理。
2.若是第1個位置,讓新結點s的next指向頭指標ptrl。
3.return s,此時s作為鍊錶的頭指標。此時的更新了鍊錶的頭指標。
4.若不是第1個位置,首先找到要插入結點的前驅結點,讓p指向這個前驅結點。
5.讓新結點s的next指向p的next,即s—>next = p—>next;
6.讓p—>next指向s,即p—>next = s;
7.return ptrl,此時ptrl還是作為鍊錶的頭指標,沒有被修改,但考慮到一致性需要這樣寫。
刪除操作如下
1.判斷要刪除的是否是第1個位置,若是需要特殊處理。
2.若是第1個位置,讓s指向要刪除的結點。首先判斷ptrl是否為空,若是直接return null;若不為空,則將鍊錶的頭結點挪到下乙個位置,即ptrl = ptrl—>next;
3.free(s);然後return ptrl
4.若不是第1個位置,首先找到要刪除結點的前驅結點,讓p指向這個前驅結點。
5.讓臨時指標q指向要刪除的結點,即q = p—>next;
6.讓p的next指向要刪除結點的下乙個結點,即p—>next = q—>next;
7.釋放q的空間,即free(q);
8.return ptrl
優勢2:統一空表和非空表的處理
若使用頭結點,無論表是否為空,頭指標都指向頭結點,也就是*lnode型別,對於空表和非空表的操作是一致的。
若不使用頭結點,當表非空時,頭指標指向第1個結點的位址,即*lnode型別,但是對於空表,頭指標指向的是null,此時空表和非空表的操作是不一致的。
3.單鏈表操作
typedef int sdatatype;
// 鍊錶的節點
typedef struct slistnode
node, *pnode;
// 鍊錶的結構,給乙個頭指標儲存鍊錶第乙個節點的位址
typedef struct slist
slist, *pslist;
// 鍊錶的初始化
void slistinit(slist* s);
void slistinit(slist* s, sdatatype data)
// 在鍊錶s最後乙個節點後插入值為data的節點
void slistpushback(slist* s, sdatatype data);
void slistpushback(slist* s, sdatatype data)
else
}// 刪除鍊錶s最後乙個節點
void slistpopback(slist* s);
void slistpopback(slist* s)
else if (null == s->_phead->_pnext)
else
free(pcur);
pcur->_pnext = null; }}
// 在鍊錶s第乙個節點前插入值為data的節點
void slistpushfront(slist* s, sdatatype data);
void slistpushfront(slist* s, sdatatype data)
// 刪除鍊錶s的第乙個節點
void slistpopfront(slist* s);
void slistpopfront(slist* s)
// 在鍊錶的pos位置後插入值為data的節點
void slistinsert(pnode pos, sdatatype data);
void slistinsert(pnode pos, sdatatype data)
pnewnode = buyslistnode(data);
pnewnode->_pnext = pos->_pnext;
pos->_pnext = pnewnode;
}// 刪除鍊錶s中pos位置的節點
void slisterase(slist* s, pnode pos);
void slisterase(slist* s, pnode pos)
if (pos == s->_phead)
else
if (pprepos)
} free(pos);
}// 在鍊錶中查詢值為data的節點,找到返回該節點的位址,否則返回null
pnode slistfind(slist* s, sdatatype data);
void slistfind(slist* s, sdatatype data)
pcur = pcur->_pnext;
} return null;
}// 獲取鍊錶中有效節點的個數
size_t slistsize(slist* s);
int slistsize(slist* s)
return count;
}// 檢測鍊錶是否為空
int slistempty(slist* s);
int slistempty(slist* s)
// 將鍊錶中有效節點清空
void slistclear(slist* s);
void slistclear(slist* s)
pcur == null;
}// 銷毀鍊錶
void slistdestroy(slist* s);
void slistdestroy(slist* s)
資料結構之單鏈表
date 08 07 06 descript 單鏈表的實現與應用 public class linlist public node gethead 定位函式 public void index int i throws exception if i 1 current head.next int j...
資料結構之單鏈表
鍊錶 儲存結構的一種,包含兩個部分,資料域和指標域,相對於順序儲存結構來說,插入和刪除的演算法時間複雜度只為o 1 定義 定義 typedef struct node linklist linklist,指標指向每乙個元素 typedef struct nodenode 以下為簡單的c語言實現 in...
資料結構之單鏈表
由於順序表再插入或者刪除時需要移動大量資料,並且如果表比較大,會比較難分配連續的儲存空間導致儲存資料失敗。因此可以採用鍊錶結構,鍊錶結構是一種動態儲存分配的結構形式,可以根據需要動態的申請所需的儲存單元。鍊錶又分為單鏈表,雙向鍊錶,以及單迴圈鍊錶,多重鏈的迴圈鍊錶。本文先介紹單鏈表。典型的單鏈表結構...