構成:結點資訊和後繼結點的指標(這兩部分組成資料元素被稱為儲存映像,也稱結點node),頭指標,頭結點(可有可無),為了區分頭節點,第乙個儲存資訊的結點叫開始結點,最後乙個結點叫終端結點
head(頭指標指向鍊錶的第乙個結點如果有頭結點,則指向頭結點) 有頭結點的鍊錶:head—>next=null,則表示鍊錶為空
沒有頭結點的鍊錶 head =null 說明鍊錶為空
頭指標具有標識作用,所以常用的頭指標冠以鍊錶的名字(指標變數的名字)。無論鍊錶是否為空,頭指標均不為空
頭結點是為了操作的統一和方便而設立的,放在第乙個元素的結點之前,其資料域一般無意義(但也可以用來存放鍊錶的長度等資訊)。
有了頭結點,對在第乙個元素結點前插入結點和刪除第一結點起操作與其他節點的操作就統一了。
儲存方式:單鏈表採用鏈式儲存結構,用一組任意的儲存單元存放線性表的元素,單鏈表不需要分配儲存空間,只要有就可以分配,鍊錶的儲存空間是多次分配的,一般鍊錶結點空間來自於整個記憶體,元素個數也不受限制。當線性表中的元素個數變化較大或者根本不知道有多大時,最好用單鏈表結構,這樣可以不需要考慮儲存空間的大小問題
儲存密度:鍊錶的儲存密度小於1,而順序表等於1
訪問方式:只能順序訪問,就是把前面的元素都乙個個的遍歷(就是挨個訪問)
靜態鍊錶:是用一維陣列來儲存的,來自於乙個結構體陣列,有結點中存放資訊和下乙個結點的陣列下標,依然用指標的指向表示元素的邏輯關係,這和一般鍊錶中next指標的地位是同等的,但是這裡的指標和c語言中的儲存位址的指標變數是不一樣的,這裡的指標式乙個儲存陣列下標的整型變數,功能類似於真實的指標,亦稱之為指標
單鏈表的儲存結構的實現
typedef stuct
lnode ,*linklist;
struct lnode
;typedef lnode linklist;
(*p) 表示p所指向的結點
(*p).data<=>p->data 表示p指向結點的資料域
(*p).next<=>p->next 表示p指向結點的指標域
p=(linklist)malloc(sizeof(lnode));系統生成的新的結點
系統**p結點:
free§
鍊錶是無法進行隨機訪問的,而是需要將元素乙個個的遍歷,這種叫順序訪問
需要的標頭檔案
#include 「stdio.h」
#include 「stdlib.h」 //提供malloc()和free()
【malloc.h 動態儲存分配函式標頭檔案,當對記憶體區進行操作時,呼叫相關函式.ansi標準建議使用stdlib.h標頭檔案,但許多c編譯要求用malloc.h,使用時應查閱有關手冊。一般來說stdlib.h包含malloc.h。】
#include 「string.h」 //提供strcpy()等
malloc函式
其函式原型如下:
• void malloc(unsigned int size);
這個函式返回的是個void型別指標,所以在使用時應注意強制型別轉換成需要的指標型別。
free函式
其函式原型如下:
• void free(void p);
這個函式是用來釋放指標p作指向的記憶體區。
全域性定義鍊錶頭尾指標 方便呼叫
struct node head= null;
struct node end = null;
基本操作
① getelem(l, i, &e) // 取第i個資料元素/這裡需要位址傳遞,也就是所謂的引用型
② listinsert(&l, i, e) // 插入資料元素
③ listdelete(&l, i, e) // 刪除資料元素
④ createlist_l(&l, n) // 建立線性表
/*getelem.c*/
status getelem
(linklist l,
int i, elemtype* e)if(
!p)*e = p->data;
// 否則查詢成功,返回結點 p 的資料。
return ok;
}
由於這個演算法的時間複雜度取決於 i 的位置,當 i = 1 時, 則不需要遍歷,而 i = n 時則遍歷n-1次才可以。因此最壞情況的時間複雜度為o(n).
單鏈表的結構中沒有定義表長,所以不能實現知道迴圈多少次,因此也就不方便使用for來控制迴圈,而選擇while語句。
(類似於陣列用的i++)鍊錶則只能用「工作指標後移」
單鏈表第 i 個資料插入結點的**
基本思想:先查詢位置,再執行插入的操作
/*listinsert*/
status listinsert
(linklist* l,
int i, elemtype e)if(
!p || j > i)
// 若到鍊錶末尾 p 為空,則說明第 i 個元素不存在;
s =(linklist)
malloc
(sizeof
(node));
//否則查詢成功,在系統中生成乙個空結點 s;
s->data = e;
//將資料元素e 賦值給s->data
s->next = p->next;
//執行插入語句,並返回成功
p->next = s;
return ok;
}
單鏈表的刪除某結點
基本思想與插入相同
/*listdelete*/
status listdelete
(linklist* l,
int i, elemtype* e)if(
!(p->next)
|| j > i)
//p的下乙個結點不存在說明鍊錶結束,意思就是i其實大於鍊錶的長度,沒有意義
q = p->next;
p->next = q->next;
//這兩句相當於p->next = p->next->next
*e = q->data;
free
(q);
//此時釋放的結點是p->next結點
return ok;
}
尾插法建立單鏈表
/*initlinklist*/
status initlinklist
(list*head)
return ok;
}
刪除整表
/*clearlist*/
status clearlist
(list*l) 刪除應該是傳遞位址
l->next =
null
; 頭節點指向空
}
有了基本的鍊錶操作思維什麼雙向鍊錶,迴圈鍊錶的操作就簡單了
注意一下迴圈雙鏈表(有無頭結點之分),判斷迴圈雙鏈表是否為空
head—>next=head;
head—>prior=head;
鍊錶基本操作
include include string h include typedef struct stust void xj st h 生成單鏈表 l l null void shc st h 輸出鍊錶 printf d n h d void chr st h 按大小插入元素 else h h l v...
鍊錶基本操作
動態記憶體的相關知識int p null 定義指標變數 p int malloc sizeof int 申請記憶體空間,並且進行強制型別轉換 p 3 使用指標變數 typedef struct list typedef struct listnode listpointer struct listn...
鍊錶基本操作
鍊錶就是c中利用結構體,將資料和下乙個結構體的位址封裝在乙個結構體中形成乙個節點,這些節點組合起來就是乙個基礎的鍊錶,根據需要可以擴充套件其中的內容來實現不同的需求。實現乙個鍊錶需要定義節點,建立,初始化,插入,刪除這些基本操作。include stdafx.h include stdlib.h i...