日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

(C语言版)链表(二)——实现单向循环链表创建、插入、删除、释放内存等简单操作

發布時間:2023/11/30 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 (C语言版)链表(二)——实现单向循环链表创建、插入、删除、释放内存等简单操作 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

http://blog.csdn.net/fisherwan/article/details/19754585

昨天寫了單向鏈表的代碼,今天上午把單向循環鏈表的程序給敲完了。鏈表的相關操作一樣的,包含鏈表的創建、判斷鏈表是否為空、計算鏈表長度、向鏈表中插入節點、從鏈表中刪除節點、刪除整個鏈表釋放內存。如果單向鏈表理解了,那單向循環鏈表也就不難了。

單向循環鏈表如下圖所示:


看圖可以知道,單向循環鏈表和單向鏈表差不多,只不過是最后的尾節點指向的不是空,而是指向頭節點。理解這一點很重要,因為這是我們寫程序的關鍵。下面我們上代碼:

SqCcLinkList.h 頭文件——定義了節點結構體,以及相關操作的函數聲明。

[cpp]?view plain?copy
  • #ifndef?ONE_WAY_CIRCULAR_LINK_LIST_H??
  • #define?ONE_WAY_CIRCULAR_LINK_LIST_H??
  • ??
  • typedef?struct?Node??
  • {??
  • ????int?data;??
  • ????struct?Node?*pNext;??
  • }NODE,?*pNODE;??
  • ??
  • //創建單向循環鏈表??
  • pNODE?CreateSgCcLinkList(void);??
  • ??
  • //打印鏈表??
  • void?TraverseSgCcLinkList(pNODE?pHead);??
  • ??
  • //判斷鏈表是否為空??
  • int?IsEmptySgCcLinkList(pNODE?pHead);??
  • ??
  • //計算鏈表的長度??
  • int?GetLengthSgCcLinkList(pNODE?pHead);??
  • ??
  • //向鏈表中插入節點??
  • int?InsertEleSgCcLinkList(pNODE?pHead,?int?pos,?int?data);??
  • ??
  • //從鏈表中刪除節點??
  • int?DeleteEleSgCcLinkList(pNODE?pHead,?int?pos);??
  • ??
  • //刪除整個鏈表,釋放內存??
  • void?FreeMemory(pNODE?*ppHead);??
  • ??
  • #endif??

  • SqCcLinkList.cpp 鏈表源文件——這里包含了各種相關操作的函數的定義。

    (1)這部分是創建鏈表,和單向鏈表一樣,一開始也是創建了一個頭節點,初始化時,頭結點的指針指向自己(這是和單向鏈表不一樣的地方)。在寫程序時,主要體現在下面的一行代碼:

    [cpp]?view plain?copy
  • p_new->pNext?=?pHead;????//這里一定是pHead,因為最后一個節點總是指著頭節點??
  • 它的意思就是沒創建一個節點,讓這個節點指向頭節點,然后就形成了一個環,也就成了循環鏈表。

    [cpp]?view plain?copy
  • #include?<stdio.h>??
  • #include?<stdlib.h>??
  • #include?"SgCcLinkLIst.h"??
  • ??
  • //創建單向循環鏈表??
  • pNODE?CreateSgCcLinkList(void)??
  • {??
  • ????int?i,?length?=?0,?data?=?0;??
  • ????pNODE?pTail?=?NULL,?p_new?=?NULL;??
  • ????pNODE?pHead?=?(pNODE)malloc(sizeof(NODE));??
  • ??
  • ????if?(NULL?==?pHead)??
  • ????{??
  • ????????printf("內存分配失敗!\n");??
  • ????????exit(EXIT_FAILURE);??
  • ????}??
  • ??????
  • ????pHead->data?=?0;??
  • ????pHead->pNext?=?pHead;??
  • ????pTail?=?pHead;??
  • ??
  • ????printf("請輸入要創建鏈表的長度:");??
  • ????scanf("%d",?&length);??
  • ??
  • ????for?(i=1;?i<length+1;?i++)??
  • ????{??
  • ????????p_new?=?(pNODE)malloc(sizeof(NODE));??
  • ??
  • ????????if?(NULL?==?p_new)??
  • ????????{??
  • ????????????printf("內存分配失敗!\n");??
  • ????????????exit(EXIT_FAILURE);??
  • ????????}??
  • ??
  • ????????printf("請輸入第%d個節點的元素值:",?i);??
  • ????????scanf("%d",?&data);??
  • ??
  • ????????p_new->data?=?data;??
  • ????????p_new->pNext?=?pHead;????//這里一定是pHead,因為最后一個節點總是指著頭節點??
  • ????????pTail->pNext?=?p_new;??
  • ????????pTail?=?p_new;??
  • ????}??
  • ??
  • ????return?pHead;??
  • }??
  • (2)這部分是獲得鏈表的相關信息,和單向鏈表一樣,頭節點不參與運算;但是和單向鏈表不同的地方就是判斷的時候是和頭結點進行比較,如何相等的話呢,說明到了鏈表的結尾。

    [cpp]?view plain?copy
  • //打印鏈表??
  • void?TraverseSgCcLinkList(pNODE?pHead)??
  • {??
  • ????pNODE?pt?=?pHead->pNext;??
  • ??
  • ????printf("鏈表打印如:");??
  • ????while?(pt?!=?pHead)??
  • ????{??
  • ????????printf("%d?",?pt->data);??
  • ????????pt?=?pt->pNext;??
  • ????}??
  • ????putchar('\n');??
  • }??
  • ??
  • //判斷鏈表是否為空??
  • int?IsEmptySgCcLinkList(pNODE?pHead)??
  • {??
  • ????if?(pHead->pNext?==?pHead)??
  • ????????return?1;??
  • ????else??
  • ????????return?0;??
  • }??
  • ??
  • //計算鏈表長度??
  • int?GetLengthSgCcLinkList(pNODE?pHead)??
  • {??
  • ????int?length?=?0;??
  • ????pNODE?pt?=?pHead->pNext;??
  • ??
  • ????while?(pt?!=?pHead)??
  • ????{??
  • ????????length++;??
  • ????????pt?=?pt->pNext;??
  • ????}??
  • ????return?length;??
  • }??
  • (3)這部分是鏈表的插入和刪除操作,和單向鏈表一樣。

    [cpp]?view plain?copy
  • //向鏈表中插入節點??
  • int?InsertEleSgCcLinkList(pNODE?pHead,?int?pos,?int?data)??
  • {??
  • ????pNODE?p_new?=?NULL;??
  • ??
  • ????if?(pos?>?0?&&?pos?<?GetLengthSgCcLinkList(pHead)?+?2)??
  • ????{??
  • ????????p_new?=?(pNODE)malloc(sizeof(NODE));??
  • ??
  • ????????if?(NULL?==?<span?style="font-family:?Arial,?Helvetica,?sans-serif;">p_new?</span><span?style="font-family:?Arial,?Helvetica,?sans-serif;">)</span>??
  • ????????{??
  • ????????????printf("內存分配失敗!\n");??
  • ????????????exit(EXIT_FAILURE);??
  • ????????}??
  • ??
  • ????????while?(1)??
  • ????????{??
  • ????????????pos--;??
  • ????????????if?(0?==?pos)??
  • ????????????????break;??
  • ????????????pHead?=?pHead->pNext;??
  • ????????}??
  • ??????????
  • ????????p_new->data?=?data;??
  • ????????p_new->pNext?=?pHead->pNext;??
  • ????????pHead->pNext?=?p_new;??
  • ??
  • ????????return?1;??
  • ????}??
  • ????else??
  • ????????return?0;??
  • }??
  • [cpp]?view plain?copy
  • <span?style="font-family:?Arial,?Helvetica,?sans-serif;">//從鏈表中刪除節點</span>??
  • [cpp]?view plain?copy
  • int?DeleteEleSgCcLinkList(pNODE?pHead,?int?pos)??
  • {??
  • ????pNODE?pt?=?NULL;??
  • ??
  • ????if?(pos?>?0?&&?pos?<?GetLengthSgCcLinkList(pHead)?+?1)??
  • ????{??
  • ????????while?(1)??
  • ????????{??
  • ????????????pos--;??
  • ????????????if?(0?==?pos)??
  • ????????????????break;??
  • ????????????pHead?=?pHead->pNext;??
  • ????????}??
  • ??
  • ????????pt?=?pHead->pNext->pNext;??
  • ????????free(pHead->pNext);??
  • ????????pHead->pNext?=?pt;??
  • ??
  • ????????return?1;??
  • ????}??
  • ????else??
  • ????????return?0;??
  • }??
  • (4)這部分是釋放內存,和單向鏈表有些不一樣,因為單向循環鏈表是個環,最后只剩下頭節點的時候要單獨處理,這個受我判斷條件的限制。當然可能有更好的方法,我們可以共同討論。這里我分了兩種情況來釋放內存。
    [cpp]?view plain?copy
  • //刪除整個鏈表,釋放內存??
  • void?FreeMemory(pNODE?*ppHead)??
  • {??
  • ????pNODE?pt?=?NULL;??
  • ??
  • ????while?(*ppHead?!=?NULL)??
  • ????{??
  • ????????if?(*ppHead?==?(*ppHead)->pNext)?//如果只有頭節點一個??
  • ????????{??
  • ????????????free(*ppHead);??
  • ????????????*ppHead?=?NULL;??
  • ????????}??
  • ????????else????????????????????//如果不止頭節點一個??
  • ????????{??
  • ????????????pt?=?(*ppHead)->pNext->pNext;??
  • ????????????free((*ppHead)->pNext);??
  • ????????????(*ppHead)->pNext?=?pt;??
  • ????????}??
  • ????}??
  • }??


  • main.cpp 測試程序源文件——這個程序通過一些簡單的交互用來測試各個函數是否實現了各自的功能。

    [cpp]?view plain?copy
  • #include?<stdio.h>??
  • #include?<stdlib.h>??
  • #include?"SgCcLinkList.h"??
  • ??
  • int?main(void)??
  • {??
  • ????int?flag?=?0,?length?=?0;??
  • ????int?position?=?0,?value?=?0;??
  • ????pNODE?head?=?NULL;??
  • ??
  • ????head?=?CreateSgCcLinkList();??
  • ??
  • ????flag?=?IsEmptySgCcLinkList(head);??
  • ????if?(flag)??
  • ????????printf("單向循環鏈表為空!\n");??
  • ????else??
  • ????{??
  • ????????length?=?GetLengthSgCcLinkList(head);??
  • ????????printf("單向循環鏈表的長度為:%d\n",?length);??
  • ????????TraverseSgCcLinkList(head);??
  • ????}??
  • ??
  • ????printf("請輸入要插入節點的位置和元素值(兩個數用空格隔開):");??
  • ????scanf("%d?%d",?&position,?&value);??
  • ????flag?=?InsertEleSgCcLinkList(head,?position,?value);??
  • ????if?(flag)??
  • ????{??
  • ????????printf("插入節點成功!\n");??
  • ????????TraverseSgCcLinkList(head);??
  • ????}?????
  • ????else??
  • ????????printf("插入節點失敗!\n");??
  • ??
  • ????flag?=?IsEmptySgCcLinkList(head);??
  • ????if?(flag)??
  • ????????printf("單向循環鏈表為空,不能進行刪除操作!\n");??
  • ????else??
  • ????{??
  • ????????printf("請輸入要刪除節點的位置:");??
  • ????????scanf("%d",?&position);??
  • ????????flag?=?DeleteEleSgCcLinkList(head,?position);??
  • ????????if?(flag)??
  • ????????{??
  • ????????????printf("刪除節點成功!\n");??
  • ????????????TraverseSgCcLinkList(head);??
  • ????????}?????
  • ????????else??
  • ????????????printf("刪除節點失敗!\n");??
  • ????}??
  • ??
  • ????FreeMemory(&head);??
  • ????if?(NULL?==?head)??
  • ????????printf("已成功刪除單向循環鏈表,釋放內存完成!\n");??
  • ????else??
  • ????????printf("刪除單向循環鏈表失敗,釋放內存未完成!\n");??
  • ??
  • ????return?0;??
  • }??
  • PS:數據結構的學習還在繼續,剛開始寫這個程序的時候,在釋放內存的時候碰到了一些問題,不過后面通過調試還是解決了。所以,我想說調試能力也是很重要的,因為調試過一篇,你對這個程序的原理也懂的差不多了。如果你們在看程序的時候發現錯誤,希望能積極指出來。

    下一站是雙向鏈表。加油吧!


    總結

    以上是生活随笔為你收集整理的(C语言版)链表(二)——实现单向循环链表创建、插入、删除、释放内存等简单操作的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。