链表的结构
文章目錄
- 1.1 鏈表的概念及結(jié)構(gòu)
- 1.2 鏈表的分類
- 1.3 鏈表的實現(xiàn)
- 1.4 雙向鏈表的實現(xiàn)
1.1 鏈表的概念及結(jié)構(gòu)
概念:鏈表是一種物理存儲結(jié)構(gòu)上非連續(xù)、非順序的存儲結(jié)構(gòu),數(shù)據(jù)元素的邏輯順序是通過鏈表中的指針鏈接次序?qū)崿F(xiàn)的
假設(shè)在32位系統(tǒng)上,節(jié)點中 值位int類型,則一個節(jié)點的大小為8個字節(jié),則也有可能有下述鏈表:
1.2 鏈表的分類
實際中鏈表的結(jié)構(gòu)非常多樣,以下情況組合起來就有8種鏈表結(jié)構(gòu):
循環(huán)或者非循環(huán)
雖然有這么多的鏈表的結(jié)構(gòu),但是我們實際中最常用還是兩種結(jié)構(gòu) :
無頭單向非循環(huán)鏈表
帶頭雙向循環(huán)鏈表
1.3 鏈表的實現(xiàn)
sList.h:
typedef int SLT;typedef struct SListNode {SLT data;struct SListNode* next; }s;//打印鏈表 void SListPrint(s* plist);// 動態(tài)申請一個節(jié)點 s* BuySListNode(SLT x);//單鏈表尾插 void SListPushBack(s** pplist, SLT x);//單鏈表頭插 void SListPushFront(s** pplist, SLT x);//單鏈表尾刪 void SListPopBack(s** pplist);//單鏈表頭刪 void SListPopFront(s** pplist);sList.c:
//創(chuàng)建新節(jié)點 s* BuySListNode(SLT x) {s* NewNode = (s*)malloc(sizeof(s));NewNode->data = x;NewNode->next = NULL;return NewNode; }//打印鏈表 void SListPrint(s *plist) {assert(plist);s* tail = plist;while (tail != NULL){printf("%d ", tail->data);tail = tail->next;}printf("\n");}//尾插 void SListPushBack(s** pplist, SLT x) {s *new = BuySListNode(x);if (*pplist == NULL){*pplist = new;}else{s* tail = *pplist;while (tail->next != NULL){tail = tail->next;}tail->next = new;} }//頭插 void SListPushFront(s** pplist, SLT x) {s *NewNode = BuySListNode(x);NewNode->next = *pplist;*pplist = NewNode;}//尾刪 void SListPopBack(s** pplist) {assert(*pplist);if ((*pplist)->next == NULL){free(*pplist);*pplist = NULL;}else{s* tail = *pplist;s* prev = NULL;while (tail->next != NULL){prev = tail;tail = tail->next;}free(tail);tail = NULL;prev->next = NULL;} }//頭刪 void SListPopFront(s** pplist) {assert(*pplist);s* tmp = *pplist;*pplist = (*pplist)->next;free(tmp);tmp = NULL;1.4 雙向鏈表的實現(xiàn)
List.h:
typedef int tp;typedef struct Listnode {struct Listnode* prev;struct Listnode* next;tp data;}List; //創(chuàng)建新節(jié)點 List* BuyListNode(tp x); // 創(chuàng)建返回鏈表的頭結(jié)點. List* ListInit(void); // 雙向鏈表打印 void ListPrint(List* phead); // 雙向鏈表尾插 void ListPushBack(List* phead, tp x); // 雙向鏈表尾刪 void ListPopBack(List* phead); // 雙向鏈表頭插 void ListPushFront(List* phead, tp x); // 雙向鏈表頭刪 void ListPopFront(List* phead); // 雙向鏈表查找 List* ListSearch(List* phead, tp x); // 雙向鏈表在pos的前面進行插入 List* ListInsert(List*phead, tp y, tp x); // 雙向鏈表刪除pos位置的節(jié)點List.c:
對于帶頭雙向循環(huán)鏈表,中間插入適用于頭插與尾插,中間刪除適用于頭刪與尾刪
看代碼即可知道
//創(chuàng)建新節(jié)點 List* BuyListNode(tp x) {List* newnode = (List*)malloc(sizeof(List));newnode->data = x;return newnode;}//初始化鏈表 List* ListInit(void) {List* phead = BuyListNode(0);phead->next = phead;phead->prev = phead; }//尾插 void ListPushBack(List* phead, tp x) {assert(phead != NULL);List* newnode = BuyListNode(x);List* tail = phead->prev;//原來的尾節(jié)點tail->next = newnode;//尾節(jié)點指向新的節(jié)點//新節(jié)點鏈接原來的尾節(jié)點和頭節(jié)點newnode->prev = tail;newnode->next = phead;//頭節(jié)點鏈接新節(jié)點phead->prev = newnode; }//打印鏈表 void ListPrint(List* phead) {assert(phead != NULL);assert(phead->next != phead);List* cur = phead->next;while (cur != phead){printf("%d ", cur->data);cur = cur->next;}printf("\n");}//頭插 void ListPushFront(List* phead, tp x) {assert(phead != NULL);List* newnode = BuyListNode(x);List* first = phead->next;//原來的首節(jié)點phead->next = newnode;newnode->prev = phead;newnode->next = first;first->prev = newnode;}//尾刪 void ListPopBack(List* phead) {assert(phead != NULL);assert(phead->next != phead);ListErase(phead,phead->prev->data); }//頭刪 void ListPopFront(List* phead) {assert(phead != NULL);assert(phead->next != phead);ListErase(phead, phead->next->data); }//暫時只考慮找到的情況 List* ListSearch(List* phead, tp x) {assert(phead != NULL);assert(phead->next != phead);List* cur = phead->next;List* pos = NULL;while (cur != phead){if (cur->data == x){pos = cur;return pos;}cur = cur->next;} }//插在pos之前 List* ListInsert(List*phead, tp y, tp x) {List* pos = ListSearch(phead, y);List* newnode = BuyListNode(x);List* posfront = pos->prev;posfront->next = newnode;newnode->prev = posfront;newnode->next = pos;pos->prev = newnode; }//刪除pos位置的結(jié)點 void ListErase(List* phead, tp y) {assert(phead != NULL);List* pos = ListSearch(phead, y);(pos->prev)->next = (pos->next);(pos->next)->prev = pos->prev;free(pos); }關(guān)于鏈表的一些題目,可以關(guān)注作者的下一篇博客一些鏈表OJ題
光講概念畢竟是枯燥的,做更多的題目我們才能加深對鏈表的理解
總結(jié)
- 上一篇: 手写LinKedList双向链表 终于
- 下一篇: 伺服电机的选型计算方法