鏈表:
順序由各對象的指針決定,可以靈活的表示動態集合,但效率不及數組高,形式如下圖所示:
next[x]指向鏈表中x的下一個元素,prev[x]指向上一個元素,head[L]指向第一個元素,若head[L]=NULL,則該鏈表爲空。
程序中使用的是雙向鏈表。
#include <stdio.h>
#include <stdlib.h>
//鏈表中的每一個元素,包含一個值x,一個指向前驅的指針prev以及指向後繼的指針next
typedef struct Node
{
int x;
struct Node* prev;
struct Node* next;
}Node;
//鏈表結構,只包含指向第一個元素的指針,初始化時設置爲NULL
typedef struct List
{
Node* first;
}List;
//鏈表的查詢,從第一個元素開始依次往下即可
Node* List_Search(List L,int k)
{
Node* N=L.first;
while(N!=NULL&&N->x!=k)
N=N->next;
return N;
}
//鏈表的插入操作,需要判斷邊界條件
//假設鏈表一開始是空的話,只需要將第一個頭指針給他即可
void List_Insert(List* L,Node* N)
{
(*N).next=(*L).first;
if((*L).first!=NULL)
(*L).first->prev=N;
(*L).first=N;
(*N).prev=NULL;
}
//鏈表的刪除操作,需要調用List_Search找到該元素的指針,同樣注意邊界條件
void List_Delete(List* L,int k)
{
Node* N=List_Search(*L,k);
if(N!=NULL)
{
if(N->prev!=NULL)
N->prev->next=N->next;
else
L->first=N->next;
if(N->next!=NULL)
N->next->prev=N->prev;
}
else
printf("鏈表中不存在該元素\n");
}
//主函數進行測試
int main()
{
List L={first:NULL};
Node N1={x:1,prev:NULL,next:NULL};
Node N2={x:2,prev:NULL,next:NULL};
Node N3={x:3,prev:NULL,next:NULL};
List_Insert(&L,&N1);List_Insert(&L,&N2);List_Insert(&L,&N3);
Node* NP;
NP=List_Search(L,4);
if(NP!=NULL)
printf("查找數據%d成功\n",NP->x);
else
printf("查找失敗\n");
List_Delete(&L,2);
List_Delete(&L,2);
return 0;
}
可以看到,無論是插入操作,還是刪除操作,都需要考慮到邊界條件,那麼,有沒有什麼辦法可以忽略邊間條件直接對鏈表進行操作呢?
帶哨兵的環形雙向鏈表:
如圖,哨兵元素nil[L]介於頭和尾之間,空鏈表只包含一個哨兵元素。
操作與原來差不多,附上源代碼:
#include <stdio.h>
#include <stdlib.h>
//元素類型依舊是結構體內的數據成員以及兩個指針
//不同的是不需要首指針而是通過設置哨兵也就是講一個元素放置在首部構成循環鏈表
//這個哨兵的區別方式是數據成員x的值爲0,那麼該元素爲哨兵節點
typedef struct Node
{
int x;
struct Node* prev;
struct Node* next;
}Node;
Node* List_Search(Node* Nil,int k)
{
Node* N=Nil->next;
while(N!=Nil&&N->x!=k)
N=N->next;
return N;
}
void List_Insert(Node* Nil,Node* N)
{
N->next=Nil->next;
Nil->next->prev=N;
Nil->next=N;
N->prev=Nil;
}
//不需要判別邊界條件,只需兩行代碼就可以解決
void List_Delete(Node* Nil,int k)
{
Node* NP=List_Search(Nil,k);
if(NP->x!=0)
{
NP->prev->next=NP->next;
NP->next->prev=NP->prev;
}
else
printf("鏈表中不存在該元素\n");
}
//主函數進行測試
int main()
{
Node Nil={x:0,prev:&Nil,next:&Nil};//不要忘記哨兵的初始化方式!
Node N1={x:1,prev:NULL,next:NULL};
Node N2={x:2,prev:NULL,next:NULL};
Node N3={x:1,prev:NULL,next:NULL};
List_Insert(&Nil,&N1);List_Insert(&Nil,&N2);List_Insert(&Nil,&N3);
Node* NP;
NP=List_Search(&Nil,2);
if(NP->x!=0)
printf("查找數據%d成功\n",NP->x);
else
printf("查找失敗\n");
List_Delete(&Nil,2);
NP=List_Search(&Nil,2);
if(NP->x!=0)
printf("查找數據%d成功\n",NP->x);
else
printf("查找失敗\n");
return 0;
}