循環雙向鏈表-C語言實現

直接貼出完整代碼,每一個函數的功能及部分代碼的解釋都在註釋中,代碼親測可行函數

 

/*
2018.8.15
注意三點:
            1.不要將循環寫成if    //很尷尬,主要是我犯了這個錯誤,找了半天還沒找出來,次日看的時候才發現,很是的尷尬
            2.循環鏈表的判空操做是  p->rear != *L
            3.p = *L,循環體中用p->rear作條件  這種寫法便於對當前結點的前一結點操做,插入、刪除、修改操做使用這種形式
              p = *L->rear,循環體中用p作條件  這種寫法便於對當前結點操做,查找、遍歷使用這種形式
       4.雙向鏈表在插入與刪除時,要處理好前驅指針和後繼指針,切不可遺忘。尤爲是插入時,要將新點以後的結點的前驅指向新結點,這裏容易被忽略
*/ #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 *pront; //指向前一結點的指針 ElemType date; //結點元素 struct Node *rear; //指向後一結點的指針 }Node; typedef struct Node *LoopList; //建立鏈表 /* 循環雙向鏈表的插入操做 */ Status LoopInsert(LoopList *L, int i, ElemType e) { int j = 1; //計數器,記錄當前位置 LoopList r = *L; //指向L //此種寫法便於對當前結點的上一結點進行操做 LoopList s; //用於建立新結點 // while(r->rear && j < i) //判非空 判位置索引合理 //循環鏈表的判斷非空不是這樣的 2018.8.15 while(r->rear != *L && j < i) { r = r->rear; //指針後移 j++; //計數器加1 } if(r->rear == *L || j > i) //判空 判位置索引不合理 return ERROR; s = (LoopList)malloc(sizeof(Node)); //開闢新結點s s->date = e; //爲s的數據域賦值 r->rear->pront = s; //使插入結點後的下一結點的前驅指向s s->rear = r->rear; //使s的後繼結點等於r的後繼結點 s->pront = r; //使s的前驅結點等於r r->rear = s; //使r得後繼結點等於s return OK; } /* 循環雙向鏈表的刪除操做 */ Status DelList(LoopList *L, int i, ElemType *e) { int j = 1; //記錄當前位置 LoopList r = *L; //指向鏈表 LoopList s; //用於釋放要刪除的結點 while(r->rear != *L && j < i) //判非空 判索引位置有效 { r = r->rear; //指針後移 j++; //計數器加1 } if(r->rear == *L || j > i) //判空 判索引位置無效 return ERROR; s = r->rear; //使s指向r *e = s->date; //將要刪除的結點數據賦值給e r->rear = s->rear; //使r的後繼結點等於r的後繼結點 s->rear->pront = r; //使s的後繼的前驅結點等於r free(s); //釋放s結點 return OK; } /* 循環雙鏈表的修改操做 */ Status UpdateList(LoopList *L, int i, ElemType e) { int j = 1; //記錄當前位置 LoopList r = (*L)->rear; //指向第一個結點 //此種寫法便於歲當前結點操做 while(r != *L && j < i) //判非空 判位置索引有效 { r = r->rear; //指針後移 j++; //計數器加1 } if(r == *L || j > i) //判空 判位置索引無效 return ERROR; r->date = e; //使r的數據域等於 e return OK; } /* 循環雙鏈表的查找 */ Status GetElem(LoopList L, int i, ElemType *e) { int j = 1; //計數器 LoopList r = L->rear; //指向第一個結點 while(r != L && j < i) //判非空 判位置索引有效 { r = r->rear; //指針後移 j++; //計數器加1 } if(r == L || j > i) //判空 判位置索引無效 return ERROR; *e = r->date; //將r的數據域內容賦值給e return OK; } /* 循環雙鏈表的正序遍歷 */ void PrintList1(LoopList L) { int j = 1; LoopList r = L->rear; //指向L第一個結點 if(r == L) //判空 printf("表空\n"); while(r != L) //判非空 { printf("第%d個結點的數據是%d\n",j,r->date); r = r->rear; j++; } printf("\n"); } /* 循環雙鏈表的倒序遍歷 */ void PrintList2(LoopList L) { int j = 1; LoopList r = L->pront; //指向L倒數第一個結點 if(r == L) //判空 printf("表空\n"); while(r != L) //判非空 { printf("倒數第%d個結點的數據是%d\n",j,r->date); r = r->pront; j++; } printf("\n"); } /* 循環雙鏈表的建立 */ Status CreatList(LoopList *L, int n) { int i; //計數器 (*L) = (LoopList)malloc(sizeof(Node)); //建立頭結點 LoopList s,q; //s用於開闢新結點,q指向表尾 srand(time(0)); //初始化隨機數種子 q = *L; //指向表尾結點 for(i = 0; i < n; i++) { s = (LoopList)malloc(sizeof(Node)); //開闢新結點 s->date = rand() % 100 + 1; //爲新結點賦值 q->rear = s; //讓表尾結點的後繼結點指向新結點 s->pront = q; //讓新結點的前驅結點指向q q = s; //表尾結點指針後移 } q->rear = *L; //使表尾結點的後繼指針指向頭結點 (*L)->pront = q; //頭指針的前驅結點指向表尾結點 return OK; } void main() { LoopList L = NULL; //建立鏈表L int i, e; //i爲元素位置,e爲元素內容 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: printf("請輸入須要建立元素的個數:"); scanf("%d", &i); if(CreatList(&L, i)) 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; default: printf("選擇錯誤\n"); break; } } }
相關文章
相關標籤/搜索