主要な双方向循環リンクリストを実現するC言語
1.二重リンクリストの構造と実現
1.1主要な双方向循環リンクリスト
構造は最も複雑で、通常、データを個別に格納するために使用されます。実際に使用されるリンクリストのデータ構造は、主導権を握る双方向の循環リンクリストです。さらに、この構造の構造は複雑ですが、コードを使用してそれを実現すると、構造が多くの利点をもたらすことがわかりますが、実装は単純であり、コードが後でいつ実装されるかがわかります。
1.2リード双方向循環リンクリストの実現
// 带头+双向+循环链表增删查改实现
typedef int LTDataType;
typedef struct ListNode
{
LTDataType _data;
struct ListNode* _next;
struct ListNode* _prev;
}ListNode;
第二に、二重リンクリストのインターフェースの実現
2.1二重リンクリストを作成する
ヘッドノードを作成し、スペースを申請します。newNode-> _ next = newNode-> _ prev = newNode;
ListNode* BuyNode(LTDataType x)
{
ListNode* newNode = (ListNode *)malloc(sizeof(ListNode));
newNode->_data = x;
newNode->_next = newNode->_prev = NULL;
return newNode;
}
// 创建返回链表的头结点.
ListNode* ListCreate()
{
ListNode* Head = BuyNode(0);
Head->_next = Head->_prev = Head;
return Head;
}
2.2二重リンクリストの破壊
//双向链表的清除,保留头节点
void ListClear(ListNode* pHead)
{
assert(pHead);
ListNode* cur = pHead->_next;
//遍历每个节点并释放
while (cur != pHead)
{
ListNode* next = cur->_next;
free(cur);
cur = next;
}
pHead->_next = pHead->_prev = pHead;
}
// 双向链表销毁
void ListDestory(ListNode** ppHead)
{
assert(*ppHead);
ListClear(*ppHead);
free(*ppHead);
*ppHead = NULL;
}
2.3二重リンクリストがposの前に挿入されます
// 双向链表在pos的前面进行插入
void ListInsert(ListNode* pos, LTDataType x)
{
assert(pos);
ListNode* prev = pos->_prev; //pos的前一个结点
ListNode* newNode = BuyNode(x);
newNode->_prev = prev; //1.
prev->_next = newNode; //2.
pos->_prev = newNode; //3.
newNode->_next = pos; //4.
}
2.4二重リンクリストは、位置posのノードを削除します
// 双向链表删除pos位置的节点
void ListErase(ListNode* pos)
{
assert(pos);
ListNode* prev = pos->_prev; //pos的前一个结点
ListNode* next = pos->_next; //pos的后一个节点
free(pos);
prev->_next = next; //1.
next->_prev = prev; //2.
}
2.5二重リンクリストの印刷
// 双向链表打印
void ListPrint(ListNode* pHead)
{
assert(pHead);
ListNode* cur = pHead->_next;
遍历每个节点并打印
while (cur != pHead)
{
ListNode* next = cur->_next; //next指向下一个节点
printf("%d ", cur->_data); //打印当前节点
cur = next; //cur指向下一个节点
}
printf("\n");
}
2.5二重リンクリストの挿入の終了
テール挿入は、実際にはヘッドノードの前にノードを挿入するため、前に作成したインターフェイスを直接呼び出すことも、自分で徐々に実装することもできます。
// 双向链表尾插
void ListPushBack(ListNode* pHead, LTDataType x)
{
assert(pHead);
ListInsert(pHead, x);
//ListNode* tail = pHead->_prev; //找到尾节点
//ListNode* newNode = BuyNode(x); //创建一个新节点
//tail->_next = newNode; //1.
//newNode->_prev = tail; //2.
//newNode->_next = pHead; //3.
//pHead->_prev = newNode; //4.
}
2.6二重リンクリストの削除を終了する
テール削除は、二重リンクリストの最後のノードを削除することであり、削除の位置は、ヘッドノードの前のノードです。
// 双向链表尾删
void ListPopBack(ListNode* pHead)
{
assert(pHead);
ListErase(pHead->_prev);
//ListNode* tail = pHead->_prev; //找到尾节点
//if (tail == pHead) //只有头节点说明双向链表为空,直接返回
//{
// return;
//}
//ListNode* prev = tail->_prev; //尾节点的前一个节点,即新的尾节点
//free(tail); //释放尾节点
//prev->_next = pHead; //1.新的尾节点next指向head
//pHead->_prev = prev; //2.head的prev指向新的尾节点
}
2.7ダブルリンクメーターヘッダーの挿入
ヘッドインサートはヘッドノードの後ろに挿入されます
// 双向链表头插
void ListPushFront(ListNode* pHead, LTDataType x)
{
assert(pHead);
ListInsert(pHead->_next, x);
}
2.8二重リンクリストヘッダーの削除
ヘッダー削除は、ヘッドノードの後の要素を削除することです
// 双向链表头删
void ListPopFront(ListNode* pHead)
{
assert(pHead);
ListErase(pHead->_next);
}
2.9二重リンクリストルックアップ
// 双向链表查找
ListNode* ListFind(ListNode* pHead, LTDataType x)
{
assert(pHead);
ListNode* cur = pHead->_next;
while (cur != pHead)
{
ListNode* next = cur->_next;
if (cur->_data == x)
{
return cur;
}
cur = next;
}
return NULL;
}
三、コードリスト
3.1 List.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<windows.h>
// 带头+双向+循环链表增删查改实现
typedef int LTDataType;
typedef struct ListNode
{
LTDataType _data;
struct ListNode* _next;
struct ListNode* _prev;
}ListNode;
// 创建返回链表的头结点.
ListNode* ListCreate();
// 双向链表销毁
void ListClear(ListNode* pHead);
void ListDestory(ListNode** ppHead);
// 双向链表打印
void ListPrint(ListNode* pHead);
// 双向链表尾插
void ListPushBack(ListNode* pHead, LTDataType x);
// 双向链表尾删
void ListPopBack(ListNode* pHead);
// 双向链表头插
void ListPushFront(ListNode* pHead, LTDataType x);
// 双向链表头删
void ListPopFront(ListNode* pHead);
// 双向链表查找
ListNode* ListFind(ListNode* pHead, LTDataType x);
// 双向链表在pos的前面进行插入
void ListInsert(ListNode* pos, LTDataType x);
// 双向链表删除pos位置的节点
void ListErase(ListNode* pos);
3.2 List.c
#include "List.h"
ListNode* BuyNode(LTDataType x)
{
ListNode* newNode = (ListNode *)malloc(sizeof(ListNode));
newNode->_data = x;
newNode->_next = newNode->_prev = NULL;
return newNode;
}
// 创建返回链表的头结点.
ListNode* ListCreate()
{
ListNode* Head = BuyNode(0);
Head->_next = Head->_prev = Head;
return Head;
}
//双向链表的清除,保留头节点
void ListClear(ListNode* pHead)
{
assert(pHead);
ListNode* cur = pHead->_next;
//遍历每个节点并释放
while (cur != pHead)
{
ListNode* next = cur->_next;
free(cur);
cur = next;
}
pHead->_next = pHead->_prev = pHead;
}
// 双向链表销毁
void ListDestory(ListNode** ppHead)
{
assert(*ppHead);
ListClear(*ppHead);
free(*ppHead);
*ppHead = NULL;
}
// 双向链表打印
void ListPrint(ListNode* pHead)
{
assert(pHead);
ListNode* cur = pHead->_next;
遍历每个节点并打印
while (cur != pHead)
{
ListNode* next = cur->_next; //next指向下一个节点
printf("%d ", cur->_data); //打印当前节点
cur = next; //cur指向下一个节点
}
printf("\n");
}
// 双向链表尾插
void ListPushBack(ListNode* pHead, LTDataType x)
{
assert(pHead);
ListInsert(pHead, x);
//ListNode* tail = pHead->_prev; //找到尾节点
//ListNode* newNode = BuyNode(x); //创建一个新节点
//tail->_next = newNode; //1.
//newNode->_prev = tail; //2.
//newNode->_next = pHead; //3.
//pHead->_prev = newNode; //4.
}
// 双向链表尾删
void ListPopBack(ListNode* pHead)
{
assert(pHead);
ListErase(pHead->_prev);
//ListNode* tail = pHead->_prev; //找到尾节点
//if (tail == pHead) //只有头节点说明双向链表为空,直接返回
//{
// return;
//}
//ListNode* prev = tail->_prev; //尾节点的前一个节点,即新的尾节点
//free(tail); //释放尾节点
//prev->_next = pHead; //1.新的尾节点next指向head
//pHead->_prev = prev; //2.head的prev指向新的尾节点
}
// 双向链表头插
void ListPushFront(ListNode* pHead, LTDataType x)
{
assert(pHead);
ListInsert(pHead->_next, x);
}
// 双向链表头删
void ListPopFront(ListNode* pHead)
{
assert(pHead);
ListErase(pHead->_next);
}
// 双向链表查找
ListNode* ListFind(ListNode* pHead, LTDataType x)
{
assert(pHead);
ListNode* cur = pHead->_next;
while (cur != pHead)
{
ListNode* next = cur->_next;
if (cur->_data == x)
{
return cur;
}
cur = next;
}
return NULL;
}
// 双向链表在pos的前面进行插入
void ListInsert(ListNode* pos, LTDataType x)
{
assert(pos);
ListNode* prev = pos->_prev; //pos的前一个结点
ListNode* newNode = BuyNode(x);
newNode->_prev = prev; //1.
prev->_next = newNode; //2.
pos->_prev = newNode; //3.
newNode->_next = pos; //4.
}
// 双向链表删除pos位置的节点
void ListErase(ListNode* pos)
{
assert(pos);
ListNode* prev = pos->_prev; //pos的前一个结点
ListNode* next = pos->_next; //pos的后一个节点
free(pos);
prev->_next = next; //1.
next->_prev = prev; //2.
}
3.3 test.c
#include"List.h"
void TestList()
{
ListNode *p;
p = ListCreate();
ListPushFront(p, 5);
ListPushFront(p, 4);
ListPushFront(p, 3);
ListPushFront(p, 2);
ListPushFront(p, 1);
ListPrint(p);
ListPopFront(p);
ListPopFront(p);
ListPopFront(p);
ListPopFront(p);
ListPopFront(p);
ListPrint(p);
ListPushBack(p, 1);
ListPushBack(p, 2);
ListPushBack(p, 3);
ListPushBack(p, 4);
ListPushBack(p, 5);
ListPrint(p);
ListPopBack(p);
ListPopBack(p);
ListPopBack(p);
ListPopBack(p);
ListPopBack(p);
ListPrint(p);
//ListDestory(&p);
ListPushFront(p, 5);
ListPushFront(p, 4);
ListPushFront(p, 3);
ListPushFront(p, 2);
ListPushFront(p, 1);
ListPrint(p);
ListNode* pos = ListFind(p, 3);
pos->_data = 30;
ListPrint(p);
ListInsert(pos, 33);
ListPrint(p);
ListErase(pos);
ListPrint(p);
ListDestory(&p);
}
int main()
{
TestList();
system("pause");
return 0;
}