/本程式中包含對雙向連結清單的::建立、初始化、插入、删除、連結清單長度、查找指定元素的位置以及雙向連結清單的銷毀/
#include<stdio.h>
#include<stdlib.h>
typedef int Elemtype;
typedef struct linknode
{
Elemtype data;
struct linknode* next;
}Linknode,Linklist;
//建立循環連結清單
Linknode create()
{
Linklist head = (Linklist)malloc(sizeof(Linknode));
if (!head)
{
printf(“配置設定記憶體空間失敗\n”);
return 0;
}
head->next = head;
return head;
}
//初始化循環連結清單(頭插法)(本質上是尾插法,但是每次都将最後一個結點
//作為第一個結點,就相當于頭插法)
void initnode(Linknode* head)
{
int elem;
Linknode* target,p;
while (1)
{
printf(“請輸入資料elem”);
scanf_s("%d", &elem);
if (elem == 0)
{/當我們輸入0的時候,就代表資料已經輸入完成了,就要通過break退出循環了/
printf(“輸入完成\n”);
break;
}
for (target = head->next; target != head; target = target->next);
/上面for循環的作用是找到雙向連結清單 的最後一個結點,那我們為什麼要找該雙向連結清單的最後一個結點呢?因為我們想要通過尾插法的形式進行連結清單的插入,并且當循環結束之後target就指向了雙向連結清單中的最後一個結點了/
p = (Linknode)malloc(sizeof(Linknode));
/為插入的結點申請空間/
if (!p)
{/如果p等于NULL,那麼申請記憶體空間失敗,那麼程式就應該傳回,注意直接用return傳回就可以了/
printf(“記憶體空間配置設定失敗\n”);
return;
}
/如果記憶體申請成功,就将剛剛輸入的elem的值指派給剛剛申請記憶體空間的結點,準備插入/
p->data = elem;
Linknode* headnode = target->next;
//通過周遊得到的target已經是循環周遊的最後一個結點了,那麼target->next就是該雙向連結清單中頭指針的位址
p->next = headnode;
/這句話可以和上一行的代碼一次性的寫成p->next=target-next,直接省略掉了headnode的步驟)
并且最後幾行代碼的含義就是先将剛剛準備插入的結點的next的指針指向頭指針,然後再将原先連結清單的最後一個結點指向剛剛加入的結點/
target->next = p;
/注意p->next=target-next和 target->next = p這兩句代碼就不能交換;因為如果交換了的話, target->next = p,p->next=target-next=p,那麼p->next就會等于p,而p->next在雙向連結清單中應該指向頭指針,因為它已經為最後一個元素了/
}
}
//循環連結清單的插入資料
void insertnode(Linknode* head, Elemtype x, int i)
{
//在位置i插入資料元素為x的結點
int j = 0;
Linknode* p = head,q;
for (j = 0; p->next != head && j < i-1; j++)
{/注意for循環中j<i-1就結束的原因是:
我們為了找到插入位置的前一個位置,因為我們需要用到插入位置的前一個位置的指針,需要将該指針的位址進行一個修改,從指向原來的結點到指向新插入的結點/
/現在我們來分析為什麼是j等于i-1就結束了::
因為剛開始p結點是指向頭節點的,并且 j剛開始也初始化為0,是以當p指向第i-1個結點時,這個結點是我們需要的結點,循環就應該結束,這時j等于i-1,是以當j<i-1的時候,都可以一個一個往下找,當j=i-1的時候,循環就應該結束,即此時p已經指向了第i-1個結點了/
p = p->next;
}
/注意該for循環結束是已經找到了第i-1個結點p了/
if (p->next != head)
{//找到了合理的插入的位置
//并且p為插入位置的前一個結點
/那為什麼插入位置合理的位置的條件是p->next != head呢??現在我們來分析::
由于該連結清單是一個雙向連結清單,p為待插入結點的上一個結點,如果p->next即p的下一個結點如果不存在的話,那麼就不可能在這個位置進行插入了,即插入失敗!!那麼說明時候為p的下一個結點不存在呢??就是p->next等于head,因為該連結清單是雙向連結清單,不是單連結清單,是以它的下一個結點不存在的判斷條件不是p->next!=NULL/
q = (Linknode)malloc(sizeof(Linknode));
/如果插入位置合理的話,就為該結點申請記憶體空間/
if (!q)
{
printf(“配置設定記憶體空間失敗\n”);
return;
/如果申請記憶體空間不成功,那麼就傳回,空即return掉/
}
q->data = x;/申請記憶體空間成功,那麼就将值x賦給新增加的結點的data域,再将該節點插入即可/
q->next = p->next;
p->next = q;
printf("%d已經插入成功\n", x);
/注意插入應該從後往前插入,因為如果從前往後插入的話,即先執行p->next=q的話,那麼p結點原先的下一個結點的指針就已經找不到了,就不能完成插入的相關操作,是以要先執行q->next=p->next;在執行p->next=q;如果先執行p->next=q的話,記得要先将p->next賦給一個變量/
}
else
{
printf(“插入失敗\n”);
}
}
//循環連結清單删除資料
void deletenode(Linknode* head, int i)
{
//删除位置為i的結點
int j;
Linknode* p = head,target;
for (j = 1; p->next!=head&&j < i; j++)
{//該for循環的目的是找到删除結點的上一個結點p
p = p->next;/必須要找到插入位置的前一個結點,因為你一旦找到了準備删除的結點,就找不到該節點的前驅結點了,就無法完成删除的相關操作了/
}
if (p->next != head)//找到了合理的删除的位置
{
target = p->next;
int elem = target->data;
p->next = target->next;
free(target);
printf("%d已經删除成功\n", elem);
}
else
{
printf(“删除失敗\n”);
}
}
//統計循環連結清單的長度
void calculate(Linknode head)
{
Linknode* p = head;//将雙向連結清單的頭指針賦給一個指針變量p,因為我們不可以随意對原先雙向連結清單的頭指針進行随意的改動*/
int count = 0;//電腦
while (p->next!= head)
{/當p->next指向頭指針的時候,雙向連結清單也就所有的元素都周遊一遍了/
count++;
p = p->next;
}
printf(“該連結清單的長度為%d\n”, count);
}
//銷毀循環連結清單
void destorynode(Linknode* head)
{
Linknode* p=head->next, * q;
while (p!= head)
{
q = p;
p = p->next;
free(q);
q = NULL;
}
head = NULL;
printf(“雙向連結清單已經銷毀完畢\n”);
}
//查找雙向連結清單中指定資料的位置
void searchnode(Linknode* head, Elemtype x)
{
Linknode* p = head;
int count = 0;//計數器
for (; p!= head && p->data != x; p = p->next,count++);
/該for循環的意思是在雙向連結清單内如果找到有結點的值等于x的,就退出循環;
是以我們如果在連結清單中找到了某個結點的值是等于x的,那麼p一定不等于head;反之如果我們沒有找到,那麼p一定是等于head的,意思是一直到最後一個結點都沒有找到,是以我們可以通過該判斷條件來判斷是否找到了指定了元素,若找到了指定的元素,就傳回它的位置,該count就是用來存儲該指定的元素在雙向連結清單的位置的/
if (p != head)
{
printf(“找到了,位置為%d\n”, count);
}
else
{
printf(“沒有找到\n”);
}
}
void print(Linknode* head)
{
Linknode* p = head->next;
/注意列印是從第一個有資料的結點開始,是以應該是head->next開始/
while (p != head)
{/一直列印到最後一個結點結束/
printf("%d\t", p->data);
p = p->next;
}
}
void test01()
{
int choice=0;
Linknode*L=NULL;
L = create();
initnode(L);
print(L);
printf("\n");
deletenode(L, 2);
print(L);
printf("\n");
insertnode(L, 100, 2);
print(L);
printf("\n");
deletenode(L, 1);
print(L);
printf("\n");
calculate(L);
printf("\n");
destorynode(L);
printf("\n");
}
int main(void)
{
test01();
system(“pause”);
return 0;
}
代碼運作結果如圖所示