對于單鏈表, 由于每個節點只存儲了向后的指針,到了尾部標識就停止了向后鏈的操作,也就是說按照這樣的方式,只能索引后繼節點不能索引前驅節點。
這會帶來什么問題呢?
例如不從頭節點出發,就無法訪問到全部節點。
要解決這個問題,只需要將單鏈表中終端節點的指針端由空指針改為指向頭節點,問題就解決了。
將單鏈表中終端節點的指針端由空指針改為指向頭結點,就使整個單鏈表形成一個環,這種頭尾相接的單鏈表稱為***循環單鏈表****,簡稱循環鏈表。如下圖:
圖片.png
注·這里并不是說循環鏈表一定要有頭結點。
- 其實循環鏈表與單鏈表的主要差異就在于循環的判斷空鏈表的條件上,原來判斷head->next是否為null,現在則是head->next是否等于head。
- 由于終端節點用尾指針rear指示,這查詢終端節點是O(1),而開始節點是rear->next->next,當然也是O(1)。
循環鏈表的代碼實現(C語言)
- 循環鏈表的初始化
typedef int ElemType;
typedef struct CLinkList
{
ElemType data;
struct CLinkList *next;
} node;
//初始化循環鏈表
void ds_init(node **pNode) {
int item;
node *temp;
node *target;
printf("輸入節點的值,輸入0完成初始化\n");
while (1)
{
scanf("%d", &item);
if (item == 0)
{
return;
}
if ((*pNode) == NULL)
{
//循環鏈表只有一個節點
*pNode = (node *)malloc(sizeof(struct CLinkList));
if (!(*pNode))
{
exit(0);
}
(*pNode)->data = item;
(*pNode)->next = *pNode;
}
else
{
//找到next指向第一個節點的節點
for (target == (*pNode); target->next != (*pNode); target = target->next)
{
}
//生成一個新節點
temp = (node *)malloc(sizeof(struct CLinkList));
if (!temp)
{
exit(0);
}
temp->data = item;
temp->next = *pNode;
target->next = temp;
}
}
}
- 循環鏈表中插入節點
//插入節點
//參數:鏈表的第一個節點,插入位置
void ds_insert(node **pNode, int i) {
node *temp;
node *target;
node *p;
int item;
int j = 1;
printf("輸入要插入節點的值:");
scanf("%d", &item);
if (i == 1) {
//新插入的節點作為第一個節點
temp = (node*)malloc(sizeof(struct CLinkList));
if (!temp)
{
exit(0);
}
temp->data = item;
//尋找最后一個節點
for (target = (*pNode); target->next != (*pNode); target = target->next)
{
}
temp->next = (*pNode);
target->next = temp;
*pNode = temp;
}
else
{
target = *pNode;
for (; j < (i - 1); ++j)
{
target = target->next;
}
temp = (node*)malloc(sizeof(struct CLinkList));
temp->data = item;
p = target->next;
target->next = temp;
temp->next = p;
}
}
- 循環鏈表中刪除節點
//刪除節點
void ds_delete(node **pNode, int i) {
node *target;
node *temp;
int j = 1;
if (i == 1)
{
//刪除的是第一個節點
//找到最后一個節點
for (target = (*pNode); target->next != (*pNode); target = target->next)
{
}
temp = *pNode;
*pNode = (*pNode)->next;
target->next = *pNode;
free(temp);
}
else
{
target = *pNode;
for (; j < i - 1; ++j)
{
target = target->next;
}
temp = target->next;
target->next = temp->next;
free(temp);
}
}
- 循環鏈表中查找節點所在位置
//返回節點所在的位置
int ds_search(node *pNode, int elem) {
node *target;
int i = 1;
for (target = pNode; target->data != elem && target->next != pNode; ++i)
{
target = target->next;
}
if (target->next == pNode)
{
//表中不存在該元素
return 0;
}
else
{
return i;
}
}