小码农教你双链表

「这是我参与11月更文挑战的第16天,活动详情查看:2021最后一次更文挑战

双链表

双链表结构图

image-20211028225455233

双链表节点

typedef int LTDataType;  //C++中的双链表是用list表示的

typedef struct ListNode
{
	LTDataType data;
	struct ListNode* next;
	struct ListNode* prev;
}LTNode;
复制代码

双链表初始化函数ListInit


//双链表初始化函数
LTNode* ListNodeInit()
{
	//创建一个双链表哨兵位头结点  不存储有效数据  循环
	LTNode* phead = (LTNode*)malloc(sizeof(LTNode));
	phead->next = phead;
	phead->prev = phead;
	return phead;
}
复制代码
image-20211028230625085

双链表尾插函数ListPushBack

image-20211029001350843


//双链表尾插函数
void ListNodePushBack(LTNode* phead, LTDataType x)
{
	assert(phead);//实际上phead永远也不可能是NULL
	LTNode* tail = phead->prev;
	LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));
	newnode->data = x;
	tail->next = newnode;
	newnode->prev = tail;
	newnode->next = phead;
	phead->prev = newnode;
}
复制代码

双链表打印函数ListPrint

image-20211029070928255

//双链表打印函数
void ListPrint(LTNode* phead)
{
	assert(phead);
	LTNode* cur = phead->next;
	while (cur != phead)
	{
		printf("%d ", cur->data);
		cur = cur->next;
	}
	printf("\n");
}
复制代码

双链表尾删函数ListPopBack

image-20211029072838324

//双链表尾删函数
void ListPopBack(LTNode* phead)
{
	assert(phead && phead->next != phead);
	LTNode* tail = phead->prev;
	LTNode* cur = phead->prev;
	tail = tail->prev;
	tail->next = phead;
	phead->prev = tail;
	free(cur);
}
复制代码

双链表头插函数ListPushFront

image-20211029080341212

//双链表头插函数
void ListPushFront(LTNode* phead, LTDataType x)
{
	assert(phead);
	LTNode* next = phead->next;//在next和phead中间插一个节点
	/*LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));
	newnode->data = x;*/
	LTNode* newnode = BuyListNode(x);
	newnode->next = next;
	next->prev = newnode;
	phead->next = newnode;
}
复制代码

既然我们头插尾插都遇到了添加节点,所以我们把添加节点的部分抽离出来重新封装一下

获得双链表节点函数BuyListNode

image-20211029191337400

//获得双链表节点函数
LTNode* BuyListNode(LTDataType x)
{
	LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));
	newnode->data = x;
	newnode->next = NULL;
	newnode->prev = NULL;
	return newnode;
}
复制代码

双链表头删函数ListPopFront

image-20211029193358759

//双链表头删函数
void ListPopFront(LTNode* phead)
{
	assert(phead && phead->next != phead);
	LTNode* next = phead->next;
	phead->next = next->next;
	next->next->prev = phead;
	free(next);
}
复制代码

双链表查找函数ListFind

这个一般是和插入,删除配合使用

//双链表查找函数
LTNode* ListFind(LTNode* phead, LTDataType x)
{
	assert(phead);
	LTNode* cur = phead->next;
	while (cur != phead)
	{
		if (cur->data == x)
			return cur;
		cur = cur->next;
	}
	return NULL;
}
复制代码

双链表插入函数ListInsert(pos之前插入因为c++中就是之前插入的)

image-20211029204212625

//双链表插入函数
void ListInsert(LTNode* pos, LTDataType x)
{
	assert(pos);
	LTNode* newnode = BuyListNode(x);
	LTNode* posprev = pos->prev;
	newnode->data = x;
	pos->prev = newnode;
	newnode->next = pos;
	newnode->prev = posprev;
	posprev->next = newnode;
}
复制代码

双链表删除函数ListErase(删除pos)

image-20211029205627363

//双链表删除函数
void ListErase(LTNode* pos)
{
	assert(pos && pos->next);
	LTNode* posnext = pos->next;
	LTNode* posprev = pos->prev;
	posnext->prev = posprev;
	posprev->next = posnext;
	free(pos);
}
复制代码

双链表销毁函数ListDestroy(实际上我在这里写报错了,前面一个函数有bug,但是找到了)

//双链表销毁函数
void ListDestroy(LTNode* phead)
{
	assert(phead);
	LTNode* tail = phead->prev;
	while (tail != phead)
	{
		LTNode* tailprev = tail->next;
		free(tail);
		tail = tailprev;
	}
	free(phead);
	phead = NULL;
}
复制代码

代码

DoubleList.h

#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
typedef int LTDataType;  //C++中的双链表是用list表示的

typedef struct ListNode
{
	LTDataType data;
	struct ListNode* next;
	struct ListNode* prev;
}LTNode;

//双链表初始化函数
extern LTNode* ListInit();
//双链表销毁函数
extern void ListDestroy(LTNode* phead);
//双链表尾插函数
extern void ListPushBack(LTNode* phead, LTDataType x);
//双链表打印函数
extern void ListPrint(LTNode* phead);
//双链表尾删函数
extern void ListPopBack(LTNode* phead);
//获得双链表节点函数
extern LTNode* BuyListNode(LTDataType x);
//双链表头插函数
extern void ListPushFront(LTNode* phead, LTDataType x);
//双链表头删函数
extern void ListPopFront(LTNode* phead);
//双链表查找函数
extern LTNode* ListFind(LTNode* phead, LTDataType x);
//双链表插入函数
extern void ListInsert(LTNode* pos, LTDataType x);
//双链表删除函数
extern void ListErase(LTNode* pos);

复制代码

DoubleList.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "DoubleList.h"

//双链表初始化函数
LTNode* ListInit()
{
	//创建一个双链表哨兵位头结点  不存储有效数据  循环
	LTNode* phead = (LTNode*)malloc(sizeof(LTNode));
	phead->next = phead;
	phead->prev = phead;
	return phead;
}
//获得双链表节点函数
LTNode* BuyListNode(LTDataType x)
{
	LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));
	newnode->data = x;
	newnode->next = NULL;
	newnode->prev = NULL;
	return newnode;
}
//双链表尾插函数
void ListPushBack(LTNode* phead, LTDataType x)
{
	assert(phead);//实际上phead永远也不可能是NULL
	LTNode* tail = phead->prev;
	/*LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));
	newnode->data = x;*/
	LTNode* newnode = BuyListNode(x);
	tail->next = newnode;
	newnode->prev = tail;
	newnode->next = phead;
	phead->prev = newnode;
}
//双链表打印函数
void ListPrint(LTNode* phead)
{
	assert(phead);
	LTNode* cur = phead->next;
	while (cur != phead)
	{
		printf("%d ", cur->data);
		cur = cur->next;
	}
	printf("\n");
}
//双链表尾删函数
void ListPopBack(LTNode* phead)
{
	assert(phead && phead->next != phead);
	LTNode* tail = phead->prev;
	LTNode* cur = phead->prev;
	tail = tail->prev;
	tail->next = phead;
	phead->prev = tail;
	free(cur);
}

//双链表头插函数
void ListPushFront(LTNode* phead, LTDataType x)
{
	assert(phead);
	LTNode* next = phead->next;//在next和phead中间插一个节点
	/*LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));
	newnode->data = x;*/
	LTNode* newnode = BuyListNode(x);
	newnode->next = next;
	next->prev = newnode;
	phead->next = newnode;
}

//双链表头删函数
void ListPopFront(LTNode* phead)
{
	assert(phead && phead->next != phead);
	LTNode* next = phead->next;
	phead->next = next->next;
	next->next->prev = phead;
	free(next);
}

//双链表查找函数
LTNode* ListFind(LTNode* phead, LTDataType x)
{
	assert(phead);
	LTNode* cur = phead->next;
	while (cur != phead)
	{
		if (cur->data == x)
			return cur;
		cur = cur->next;
	}
	return NULL;
}
//双链表插入函数
void ListInsert(LTNode* pos, LTDataType x)
{
	assert(pos);
	LTNode* newnode = BuyListNode(x);
	LTNode* posprev = pos->prev;
	newnode->data = x;
	pos->prev = newnode;
	newnode->next = pos;
	newnode->prev = posprev;
	posprev->next = newnode;
}
//双链表删除函数
void ListErase(LTNode* pos)
{
	assert(pos && pos->next);
	LTNode* posnext = pos->next;
	LTNode* posprev = pos->prev;
	posnext->prev = posprev;
	posprev->next = posnext;
	free(pos);
}
//双链表销毁函数
void ListDestroy(LTNode* phead)
{
	assert(phead);
	LTNode* tail = phead->prev;
	while (tail != phead)
	{
		LTNode* tailprev = tail->next;
		free(tail);
		tail = tailprev;
	}
	free(phead);
	phead = NULL;
}
复制代码

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "DoubleList.h"
void TestList1()
{
	LTNode* plist = ListInit();
	ListPushBack(plist, 1);
	ListPushBack(plist, 2);
	ListPushBack(plist, 3);
	ListPushBack(plist, 4);
	ListPrint(plist);
	ListPopBack(plist);
	ListPopBack(plist);
	ListPopBack(plist);
	ListPopBack(plist);
	ListPrint(plist);
	ListPushFront(plist, 10);
	ListPushFront(plist, 20);
	ListPushFront(plist, 30);
	ListPrint(plist);
	LTNode* p1 = ListFind(plist, 10);
	if (p1)
	{
		ListInsert(p1, 100);
	}
	ListPrint(plist);
	LTNode* p2 = ListFind(plist, 20);
	if (p2)
	{
		ListErase(p2);
	}
	ListPrint(plist);
	ListDestroy(plist);
	plist = NULL;
}


int main()
{
	TestList1();
	return 0;
}

复制代码

也欢迎大家能来到我们小伙伴的社区 慧编程开源俱乐部

猜你喜欢

转载自juejin.im/post/7030977068242305061