一、單鏈表:以元素 + 指標(指示後繼元素位置) = 結點(表示資料元素)
以線性表中的第乙個資料元素a1的儲存位址作為線性表的位址,稱作線性表的頭指標。
為了操作方便,在第乙個結點之前虛加乙個「頭結點」,以指向結點的指標為鍊錶的頭指標。
二、結點和單鏈表的c語言描述
adt(abstract data type):抽象資料型別
typedef struct lnodelnode, *linklist;
注:理解:typedef (struct lnode*) (linklist)
linklist l; //l為單鏈表的頭指標。
三、單鏈表操作的實現
getelem(l, i, &e) //取第i個資料元素
listinsert(&l, i, e) //插入資料元素
listdelete(&l, i, e) //刪除資料元素
clearlist(&l) //重新置為乙個空表
createlist(&l, n) //生成含n個資料元素的鍊錶
線性表的操作:
getelem(l, i, &e)在單鏈表中的實現:
單鏈表是一種順序訪問的結構,為找第i個資料元素,必須先找到第i - 1個資料元素。
因此,查詢第i個資料元素的基本操作為:移動指標,比較j(計數器)和i。
令指標p始終指向線性表中第j個資料元素。
status getelem_l(linklist l, int i, elemtype &e)
if(!p || j > i)
return error; //元素不存在 or i值不合理
e = p -> data; //取得第i個元素
return ok;
}//getelem_l
時間複雜度:o(n)--> o(listlength(l))
線性表的操作:
listinsert(&l, i, e)在單鏈表中的實現:
在鍊錶中插入結點只需要修改指標。
但同時,若要在第i個結點之前插入元素,修改的是第i - 1個結點之前的指標。
因此,在單鏈表中第i個結點之前進行插入的基本操作為:
找到線性表中第i - 1個結點,然後修改其指向後繼的指標。
status listinsert_l(linklist &l, int i, elemtype e)
if(!p || j > i - 1) //......
return error;
s = new lnode;
//生成新節點
if(s == null)
return error;
s -> data = e; //插入
s -> next = p -> next;
p -> next = s;
return ok;
}演算法的時間複雜度:o(listlength(l)) --> 這裡的複雜度與順序表的插入複雜度o(n)是有區別的!!!
主要體現在查詢方面 --> 具體操作方面 o(1)
前插結點:設p指向鍊錶中某結點,s指向待插入的為x的新結點,將*s插入到*p的前面。
(第一種方法)與後插不同的是:首先要找到*p的前驅*q(...),然後再完成在*q之後
插入*s, 設單鏈表頭指標為l。
操作如下:
1. q = l;
while( q -> next != p) //找到*p的直接前驅
q = q -> next;
s -> next = q -> next;
q -> next = s;
時間複雜度:o(n)
(第二種方法)前插操作需要找*p的前驅。(上乙個方法)可以將*s插入到*p的後面(後插)
2. s -> next = p -> next;
p -> next = s;
然後再交換資料域即可;
p -> data = s -> data;
時間複雜度:o(1)
線性表的操作:
listdelete(&l, i, &e)在單鏈表中的實現:
基本操作:
找到線性表中第i - 1個結點,修改其指向後繼的指標。
q = p -> next;
p -> next = q -> next;
e = q -> data;
delete(q);
也可以:
p -> next = p -> next -> next;
dalete(...)// 可見這種方法的弊端了吧
status listdelete_l(linklist &l, int i, elemtype &e)
//......
if(!(p -> next) || j > i - 1)
return error;
//刪除並釋放結點
q = p -> next;
p -> next = q -> next;
e = q -> data;
delete(q);
return ok;
}//listdelete_l
時間複雜度:o(n)
線性表的操作:
clearlist(&l)在單鏈表中的實現:
void clearlist(&l)
}時間複雜度:o(n)
頭插法:逆位序輸入n個資料元素的值,建立帶頭結點的單鏈表。
例: 輸入 1, 2, 3, 4, 5
得到 5, 4, 3, 2, 1
操作步驟:
一、建立乙個"空表";
二、輸入資料元素an, 建立結點並插入;
三、輸入資料元素a(n -1), 建立結點並插入;
四、依次類推,直到a1;
void createlist_l(linklist &l, int n)
}時間複雜度:o(n)
尾插法:.....(向對於頭插法)。
(老頭子們的)定義:正序輸入n個資料元素的值。
建立不帶頭結點的單鏈表尾插法:
linklist create_linklist2()
if(r != null) //非空表最後結點的指標域為空
r -> next = null;
return l;
}建立帶頭結點的單鏈表尾插法:
linklist create_linklist2()
r -> next = null;
return l;
}頭結點的兩個優點:
a、由於開始結點的位置被存放在頭結點的指標域中,所以在鍊錶的第乙個位置上的操作
就和在表中的其他位置上的操作一致,無需進行特殊處理;
b、無論鍊錶是否為空,其頭指標是指向頭結點的非空指標(空表中頭結點的指標域為空)
因此空表和非空表的處理就統一了唄。
線性表的鏈式儲存結構
線性表的鏈式儲存結構 順序儲存結構不足的解決辦法 缺點 最大的缺點就是插入和刪除時需要移動大量元素。為了表示每個資料元素 ai與其直接後續資料元素 ai 1 之間的邏輯關係,對資料元素 ai來說,除了儲存其本身的資訊之外,還需儲存乙個指示其直接後續的資訊。我們把儲存資料元素資訊的域稱為資料域,把儲存...
線性表的鏈式儲存結構
線性表的鏈式儲存結構,雙向鍊錶實現 package 線性表 public class dulinklist public node t data,node prev,node next 儲存該鍊錶的頭節點 private node header 儲存該鍊錶的尾節點 private node tail...
線性表的鏈式儲存結構
順序儲存結構的缺點 插入和刪除時需要移動大量元素 鏈式儲存結構的特點 用一組任意的儲存單元儲存線性表的資料元素 資料結構 儲存分配方式 時間效能 空間效能 順序儲存結構 用一段連續的儲存單元一次儲存線性表的資料元素 查詢 o 1 插入刪除 o n 需要預分配儲存空間,分大了浪費,分小了易發生上溢 單...