前面已經對單鏈表做了一些解釋。鏈表在進行循環遍歷時效率不高,但是插入和刪除時優勢明顯。
單鏈表實際上是由節點(Node)組成的,一個鏈表擁有不定數量的節點。而向外暴露的只有一個頭節點(Head),我們對鏈表的所有操作,都是直接或者間接地通過其頭節點來進行的。節點(Node)是由一個需要儲存的對象及對下一個節點的引用組成的。也就是說,節點擁有兩個成員:儲存的對象、對下一個節點的引用。其實應該用數據和地址代替前面的對象和引用的。
單鏈表的結構示意圖(包括空的單鏈表):

那么大家可能清楚了,為什么說有了頭節點就可以操作所有節點。因為有連續不斷的引用嘛!那么在鏈表里的屬性大概就只有兩個了:頭節點和節點數量。當然,根據需要,我們通常需要更多的屬性。
下面用C語言簡單寫一個單鏈表,並完成初始化,創建鏈表與鏈表遍歷。
#include <stdio.h> #include <stdlib.h> #include <time.h> typedef int ElemType; /* ElemType類型根據實際情況而定,這里假設為int */ /* 定義單鏈表結點類型 */ typedef struct Node{ ElemType element; struct Node *next; }Node; /* 1.初始化線性表,即置單鏈表的表頭指針為空 */ void initList(Node **pNode) { *pNode = NULL; printf("initList函數執行,初始化成功\n"); } /* 2.創建線性表,此函數輸入負數終止讀取數據*/ Node *creatList(Node *pHead) { Node *p1; Node *p2; p1=p2=(Node *)malloc(sizeof(Node)); //申請新節點 if(p1 == NULL || p2 ==NULL) { printf("內存分配失敗\n"); exit(0); } memset(p1,0,sizeof(Node)); scanf("%d",&p1->element); //輸入新節點 p1->next = NULL; //新節點的指針置為空 while(p1->element > 0) //輸入的值大於0則繼續,直到輸入的值為負 { if(pHead == NULL) //空表,接入表頭 { pHead = p1; } else { p2->next = p1; //非空表,接入表尾 } p2 = p1; p1=(Node *)malloc(sizeof(Node)); //再重申請一個節點 if(p1 == NULL || p2 ==NULL) { printf("內存分配失敗\n"); exit(0); } memset(p1,0,sizeof(Node)); scanf("%d",&p1->element); p1->next = NULL; } printf("creatList函數執行,鏈表創建成功\n"); return pHead; //返回鏈表的頭指針 } /* 3.打印鏈表,鏈表的遍歷*/ void printList(Node *pHead) { if(NULL == pHead) //鏈表為空 { printf("PrintList函數執行,鏈表為空\n"); } else { while(NULL != pHead) { printf("%d ",pHead->element); pHead = pHead->next; } printf("\n"); } } int main() { Node *pList = NULL; int length = 0; ElemType posElem; initList(&pList); //鏈表初始化 printList(pList); //遍歷鏈表,打印鏈表 printf("請為鏈表輸入節點值,輸入負數退出 \n"); pList=creatList(pList); //創建鏈表 printList(pList); }
鏈表是由不定數量的節點連接(通過相互之間的引用)起來的,由於這種關系,在鏈表里我們只定義了頭節點和節點數量。節點是由存儲的對象及對下一個“節點”的引用封裝而成。