資料結構之迴圈雙鏈表
阿新 • • 發佈:2020-08-10
LoopDLink.cpp 原始碼
1. 標頭檔案包含
#include <stdio.h> #include<malloc.h> #include<stdlib.h> #include<time.h> typedef int ElemType; //元素型別 typedef int Status; //返回型別 #define OK 1; //函式執行成功返回值 #define ERROR 0; //函式執行失敗返回值 typedef struct Node { struct Node *prior; //指向前一結點的指標 ElemType date; //結點元素 struct Node *next; //指向後一結點的指標 }Node, *LoopDList;
2. 建立迴圈雙鏈表
/* * 迴圈雙鏈表的建立 */ Status CreatList(LoopDList &L, int *arr, int n) { int i; //計數器 L = (LoopDList)malloc(sizeof(Node)); //建立頭結點 L->next = L; L->prior = L; LoopDList s,p; //s用於開闢新結點,p指向表尾 p = L; //指向表尾結點 for(i = 0; i < n; i++) { s = (LoopDList)malloc(sizeof(Node)); //開闢新結點 s->date = arr[i]; //為新結點賦值 p->next = s; //讓表尾結點的後繼結點指向新結點 s->prior = p; //讓新結點的前驅結點指向p p = s; //表尾結點指標後移 } p->next = L; //使表尾結點的後繼指標指向頭結點 L->prior = p; //頭指標的前驅結點指向表尾結點 return OK; }
3. 插入操作
/* * 迴圈雙向連結串列的插入操作 */ Status LoopInsert(LoopDList &L, int i, ElemType e) { int j = 1; //計數器,記錄當前位置 LoopDList p = L; //指向L //此種寫法便於對當前結點的上一結點進行操作 LoopDList s; //用於建立新結點 // while(p->next && j < i) //判非空 判位置索引合理 //迴圈連結串列的判斷非空不是這樣的 2018.8.15 while(p->next != L && j < i) { p = p->next; //指標後移 j++; //計數器加1 } if(p->next == L || j > i) //判空 判位置索引不合理 return ERROR; s = (LoopDList)malloc(sizeof(Node)); //開闢新結點s s->date = e; //為s的資料域賦值 s->prior = p->prior; s->next = p; p->prior->next = s; p->prior = s; #if 0 p->next->prior= s; //使插入結點後的下一結點的前驅指向s s->next = p->next; //使s的後繼結點等於p的後繼結點 s->prior= p; //使s的前驅結點等於p p->next = s; //使p得後繼結點等於s #endif return OK; }
4. 刪除操作
/*
* 迴圈雙向連結串列的刪除操作
* p = *L,迴圈體中用p->next做條件 這種寫法便於對當前結點的前一結點操作,插入、刪除、修改操作使用這種形式
*/
Status DelList(LoopDList &L, int i, ElemType *e)
{
int j = 1; //記錄當前位置
LoopDList p = L; //指向連結串列
LoopDList s; //用於釋放要刪除的結點
while(p->next != L && j < i) //判非空 判索引位置有效
{
p = p->next; //指標後移
j++; //計數器加1
}
if(p->next == L || j > i) //判空 判索引位置無效
return ERROR;
s = p->next; //使s指向p
*e = s->date; //將要刪除的結點資料賦值給e
p->next = s->next; //使p的後繼結點等於r的後繼結點
s->next->prior = p; //使s的後繼的前驅結點等於p
free(s); //釋放s結點
return OK;
}
5. 查詢操作
/*
* 迴圈雙鏈表的查詢
* p = *L->next,迴圈體中用p做條件 這種寫法便於對當前結點操作,查詢、遍歷使用這種形式
*/
Status GetElem(LoopDList L, int i, ElemType *e)
{
int j = 0; //計數器
LoopDList p = L->next; //指向第一個結點
while(p != L && j < i) //判非空 判位置索引有效
{
p = p->next; //指標後移
j++; //計數器加1
}
if(p == L || j > i) //判空 判位置索引無效
return ERROR;
*e = p->date; //將p的資料域內容賦值給e
return OK;
}
6. 修改操作
/*
* 迴圈雙鏈表的修改操作
*/
Status UpdateList(LoopDList *L, int i, ElemType e)
{
int j = 1; //記錄當前位置
LoopDList r = (*L)->next; //指向第一個結點 //此種寫法便於歲當前結點操作
while(r != *L && j < i) //判非空 判位置索引有效
{
r = r->next; //指標後移
j++; //計數器加1
}
if(r == *L || j > i) //判空 判位置索引無效
return ERROR;
r->date = e; //使r的資料域等於 e
return OK;
}
7.正序遍歷
/*
* 迴圈雙鏈表的正序遍歷
*/
void PrintList1(LoopDList L)
{
LoopDList p = L->next; //指向L第一個結點
if(p == L) //判空
printf("表空\n");
while(p != L) //判非空
{
if(p->next != L)
printf("[%d] -> ", p->date);
else
printf("[%d]",p->date);
p = p->next;
}
printf("\n");
}
8. 倒序遍歷
/*
迴圈雙鏈表的倒序遍歷
*/
void PrintList2(LoopDList L)
{
LoopDList p = L->prior; //指向L倒數第一個結點
if(p == L) //判空
printf("表空\n");
while(p != L) //判非空
{
if(p->prior != L)
printf("[%d] -> ", p->date);
else
printf("[%d]",p->date);
p = p->prior;
}
printf("\n");
}
9. 測試函式
int main()
{
LoopDList L = NULL; //建立連結串列L
int i, e; //i為元素位置,e為元素內容
int n = 0;
int arr[10] = {0,1,2,3,4,5,6,7,8,9};
n = sizeof(arr)/sizeof(arr[0]);
while(true)
{
printf("請選擇對線性連結串列的操作:\n");
printf("1.建立\n");
printf("2.插入\n");
printf("3.刪除\n");
printf("4.查詢\n");
printf("5.修改\n");
printf("6.正序輸出\n");
printf("7.倒序輸出\n");
printf("8.退出\n");
int a;
scanf("%d", &a);
switch(a)
{
case 1:
if(CreatList(L, arr, n))
printf("建立成功\n");
else
printf("建立失敗\n");
break;
case 2:
printf("請輸入需要插入的位置:");
scanf("%d", &i);
printf("請輸入需要插入的元素:");
scanf("%d", &e);
if(LoopInsert(L, i, e))
printf("插入成功\n");
else
printf("插入失敗\n");
break;
case 3:
printf("請輸入需要刪除的位置:");
scanf("%d", &i);
if(DelList(L, i, &e))
printf("刪除成功\n");
else
printf("刪除失敗\n");
break;
case 4:
printf("請輸入需要查詢的位置:");
scanf("%d", &i);
GetElem(L, i, &e);
printf("第%d個元素為%d\n",i,e);
break;
case 5:
printf("請輸入需要修改的位置:");
scanf("%d", &i);
printf("請輸入新的的元素:");
scanf("%d", &e);
if(UpdateList(&L, i, e))
printf("修改成功\n");
else
printf("修改失敗\n");
break;
case 6:
if(L == NULL)
{
printf("表還未建立\n");
break;
}
PrintList1(L);
break;
case 7:
if(L == NULL)
{
printf("表還未建立\n");
break;
}
PrintList2(L);
break;
case 8:
return -1;
default:
printf("選擇錯誤\n");
break;
}
}
return 0;
}
參考
雙鏈表實現1: https://blog.csdn.net/weixin_43810205/article/details/88626582
雙鏈表實現2: https://www.cnblogs.com/likewithyou/p/5842984.html
圖解連結串列: https://wk.baidu.com/view/b3cc07abb04e852458fb770bf78a6529647d35cc?pcf=2
迴圈單鏈表: https://www.cnblogs.com/yurui/p/9503164.html