C語言單鏈表及基本操作的實現
阿新 • • 發佈:2018-12-16
資料結構中,單向連結串列(又名單鏈表、線性連結串列)是連結串列的一種,其特點是連結串列的連結方向是單向的,對連結串列的訪問要通過從頭部開始,依序往下讀取。
下面的程式碼是使用指標實現的一個單鏈表,稱為動態單鏈表;當然,也可以使用陣列實現一個單鏈表,為靜態單鏈表,後面學習之後,再用陣列實現單鏈表。
完整程式碼如下:
一、定義標頭檔案:list.h
#ifndef LIST_H_INCLUDED #define LIST_H_INCLUDED struct Node; typedef struct Node *PtrToNode; typedef PtrToNode List; typedef PtrToNode Position; List MakeEmpty(List L); //生成空連結串列L void DestroyList(List L); //銷燬連結串列L _Bool IsEmpty(List L); //判定連結串列是否為空 _Bool IsLast(Position P, List L); //判定位置P的節點是否為尾結點 int Length(List L); //檢視連結串列長度 Position Find(int X, List L); //在連結串列L中查詢資料項為X的第一個結點 void Delete(int X, List L); //在連結串列L中刪除資料項為X的第一個結點 Position FindPrevious(int X, List L); //在連結串列L中查詢資料項為X的第一個結點的前驅位置 Position FindNext(int X,List L); //在連結串列L中查詢資料項為X的第一個結點的後繼位置 void Insert(int X, List L, Position P); //在連結串列L中P位置插入資料項為X的結點 void DeleteList(List L); //刪除連結串列L頭結點外的所有結點 Position Header(List L); //獲得連結串列L中頭結點位置 Position First(List L); //獲得連結串列L中第一個資料結點的位置 Position Advance(Position P); //獲得P位置的後繼結點位置 int Retrieve(Position P); //獲取P位置結點的資料項 struct Node { int data; Position next; }; #endif // LIST_H_INCLUDED
二、各個函式的實現: list.c
#include "list.h" #include <malloc.h> #include <stdlib.h> #include<stdio.h> /*初始化:建立一個空的單鏈表*/ List MakeEmpty(List L) { L = (PtrToNode)malloc(sizeof(PtrToNode)); //建立一個頭結點 if(!L) { printf("申請空間失敗!\n"); exit(0); } L->data = 0; //無效值,不賦值的話就是隨機值 L->next = NULL; return L; } /*銷燬連結串列L*/ void DestroyList(List L) { Position P, Temp; P = L; while(P->next != NULL) { Temp = P->next; free(P); P = Temp; } } /*測試空表*/ _Bool IsEmpty(List L) { return L->next == NULL; //Return ture if L is empty } /*測試是否為尾節點*/ _Bool IsLast(Position P, List L) { return P->next == NULL; //Return ture if P is the last position in List L } /*返回連結串列長度*/ int Length(List L) { int length = 0; Position P; P = L->next; while(P) { length++; P = P->next; } return length; } /*查詢給定元素在表中的位置*/ Position Find(int X, List L) { Position P; P = L->next; while(P != NULL && P->data != X) { P = P->next; } return P; //Return Position of X in L; NULL if not found } /*刪除表中某個元素X*/ void Delete(int X, List L) { Position P, Temp; P = FindPrevious(X, L); //首先找到該元素的先前節點 if(!IsLast(P, L)) { Temp = P->next; //此時Temp即是X所在結點 P->next = Temp->next; free(Temp); } } /*查詢表元X的前驅*/ Position FindPrevious(int X, List L) { Position P; P = L; while(P->next != NULL && P->next->data != X) { P = P->next; } return P; } /*查詢表元X的後繼*/ Position FindNext(int X,List L) { Position P; P = L; while(P != NULL && P->data != X) //當P->next == X 時,說明此事P結點即為X所在元素的結點 { P = P->next; } P = P->next; //此時P即為X所在結點位置,P重新賦值為P的下一個即後繼結點 return P; } /*向表L中P位置之後插入元素*/ void Insert(int X, List L, Position P) { Position Temp; Temp = malloc(sizeof(struct Node)); if(Temp == NULL) { printf("申請空間失敗!\n"); exit(0); } Temp->data = X; Temp->next = P->next; P->next = Temp; } /*清空連結串列L*/ void DeleteList(List L) { Position P, Temp; P = L->next; //P此時為頭結點 while(P != NULL) //從頭結點開始,從前往後,依次釋放每一個結點,清除 { Temp = P->next; free(P); P = Temp; } L->next = NULL; //保留頭結點 } /*獲取位置P後繼結點的位置*/ Position Advance(Position P) { if(P != NULL) { P = P->next; } return P; } /*獲取位置為P的結點的資料項*/ int Retrieve(Position P) { if(P != NULL) return P->data; else return 0; } /*獲取連結串列L第一個結點的位置*/ Position First(List L) { if(L->next != NULL) return L->next; else return L; //為空就返回頭結點位置 } /*獲取連結串列L頭結點位置*/ Position Header(List L) { return L; }
三、main函式測試 : Main.c
#include "list.h" #include <stdio.h> #include <stdlib.h> int main(void) { List list = NULL, p; int i; list = MakeEmpty(list); if(IsEmpty(list)) printf("空表!\n"); else printf("非空!\n"); p = list; for(i=0; i<5; i++) { Insert(i*5, list, p); p = Advance(p); printf("已插入值為%d的新節點\n", i*5); } printf("連結串列長度為%d\n", Length(list)); p = FindNext(5, list); printf("資料項為5的結點的後繼結點資料項為%d \n", Retrieve(p)); Delete(10, list); p = FindNext(5, list); printf("資料項為5的結點的後繼結點資料項為%d \n", Retrieve(p)); p = First(list); printf("第一個結點資料項為%d\n", Retrieve(p)); printf("頭結點位置為%p\n", Header(list)); return 0; }