什么是双向链表?
双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。
如图:
双向链表的基本操作:头插,头删,尾插,尾删,任意位置前插入,任意位置后插入,查找节点。
代码块:
DLink.h
#pragma once #include <stdio.h> typedef int DLinkType; typedef struct DLinkNode { DLinkType data; struct DLinkNode* _next; struct DLinkNode* _prev; } DLinkNode; DLinkNode* BuyNode(DLinkType value);//创建节点 void DestroyNode(DLinkNode** PosNode);//删除节点 void PrintDlink(DLinkNode*head);//打印链表 void InitDLinkList(DLinkNode** head);//初始化 DLinkNode* PushBackDLinkList(DLinkNode*phead, DLinkType value);//尾插 void* PopBackDLinList(DLinkNode** head);//尾删 void PushFrontDLinkList(DLinkNode** head, DLinkType value);//头插 void PopFrontDLinkList(DLinkNode* head);//头删 DLinkNode* FindDLinkList(DLinkNode* head, DLinkType to_find);//查找 void InsertDLinkList(DLinkNode** head, DLinkNode* pos, DLinkType value);//在某个节点前插入元素 void InsertAfterDLinkList(DLinkNode** head, DLinkNode* pos, DLinkType value);//在某个节点后插入元素
DLink.c
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<stdlib.h> #include<Windows.h> #include<stdlib.h> #include<assert.h> #include"DLink.h" void DestroyNode(DLinkNode*PosNode) { assert(PosNode); free(PosNode); PosNode = NULL; } void PrintDlink(DLinkNode* head) { assert(head); DLinkNode*CurNode = head; printf("NULL<="); while (CurNode) { printf("%d<=>", CurNode->data); CurNode = CurNode->_next; } printf("NULL\n"); } void InitDLinkList(DLinkNode** head) { if (head == NULL) { return; } *head = NULL; } DLinkNode* BuyNode(DLinkType value) { DLinkNode* new_node = (DLinkNode*)malloc(sizeof(DLinkNode)); if (new_node != NULL) { new_node->_prev = NULL; new_node->_next = NULL; new_node->data = value; } return new_node; } DLinkNode* PushBackDLinkList(DLinkNode**head, DLinkType value)//尾插 { assert(head); DLinkNode*InsertNode = BuyNode(value); if (*head == NULL)//如果链表还没有元素 { *head = InsertNode; return InsertNode; } DLinkNode*CurNode = (*head); while (CurNode->_next != NULL)//循环到最后 { CurNode = CurNode->_next; } CurNode->_next = InsertNode; InsertNode->_next = NULL; InsertNode->_prev = CurNode; return InsertNode; } void* PopBackDLinList(DLinkNode** head) { assert(head); DLinkNode*CurNode = (*head); DLinkNode*PrevNode = NULL;//标记当前节点的前一个节点 while (CurNode->_next != NULL) { PrevNode = CurNode; CurNode = CurNode->_next; } DestroyNode(CurNode); PrevNode->_next = NULL; } void PushFrontDLinkList(DLinkNode** head, DLinkType value) { assert(head); DLinkNode*InsertNode=BuyNode(value); DLinkNode*TmpNode = (*head); (*head) = InsertNode; InsertNode->_prev = NULL; InsertNode->_next = TmpNode; return InsertNode; } void PopFrontDLinkList(DLinkNode** head) { assert(head); *head = (*head)->_next; } DLinkNode* FindDLinkList(DLinkNode* head, DLinkType to_find) { assert(head); DLinkNode*CurNode = (head); while (CurNode) { if (CurNode->data == to_find) { return CurNode; } CurNode = CurNode->_next; } } void InsertDLinkList(DLinkNode** head, DLinkNode* pos, DLinkType value) { assert(pos); if (pos == (*head))//如果pos是头节点 { PushFrontDLinkList(head, value);//头插法 return; } DLinkNode*CurNode = (*head); DLinkNode*PrevNode = NULL; DLinkNode*InsertNode = BuyNode(value); while (CurNode!= pos)//循环到pos位置 { PrevNode = CurNode; CurNode = CurNode->_next; } PrevNode->_next = InsertNode; InsertNode->_prev = PrevNode; InsertNode->_next = CurNode; CurNode->_prev = InsertNode; } void InsertAfterDLinkList(DLinkNode** head, DLinkNode* pos, DLinkType value)//任意位置后一位插入 { assert(head); DLinkNode*InsertNode = BuyNode(value); if (pos->_next == NULL) { PushBackDLinkList(head,value); return; } DLinkNode*CurNode = (*head); while (CurNode != pos) { CurNode = CurNode->_next; } InsertNode->_next = CurNode->_next; CurNode->_next->_prev = InsertNode; CurNode->_next = InsertNode; InsertNode->_prev = CurNode; }
test.c
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<Windows.h> #include<stdlib.h> #include"DLink.h" int main() { DLinkNode* DLink; InitDLinkList(&DLink); DLinkNode* tmp = PushBackDLinkList(&DLink, 1); PushBackDLinkList(&DLink, 2); PushBackDLinkList(&DLink, 3); PushBackDLinkList(&DLink, 4); //PushFrontDLinkList(&DLink, 0); //InsertAfterDLinkList(&DLink, tmp, 5); //InsertDLinkList(&DLink,tmp , 0); //PopBackDLinList(&DLink); //PopFrontDLinkList(&DLink); //FindDLinkList(DLink, 3); PrintDlink(DLink); system("pause"); return 0; }