<双向链表及模拟实现>——《Data Structure in C Train》

 目录

详细实现链接:

<双向链表(含头结点)>《数据结构(C语言版)》

1.分析实现功能、感受双向循环链表的优势:

2. 完整源码:

DDList.h:

DDList.c:

Test.c:

后记:●由于作者水平有限,文章难免存在谬误之处,敬请读者斧正,俚语成篇,恳望指教!

                                                                       ——By 作者:新晓·故知


详细实现链接:

<双向链表(含头结点)>《数据结构(C语言版)》

1.分析实现功能、感受双向循环链表的优势:

这里实现带头双向循环链表:

链接顺序:

 功能函数截图:

2. 完整源码:

DDList.h:

#pragma once
//带头双向循环链表
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>

typedef int DDLTDataType;
//typedef char DDLTDataType;

// SList
// DList

// 带头双向循环 -- 最有链表结构,任意位置插入删除数据都是O(1)
typedef struct DDListNode
{
	struct DDListNode* next;
	struct DDListNode* prev;
	DDLTDataType data;
}DDListNode;

//初始化
//为了减少二级指针的使用问题,采用返回赋值的方式解决
DDListNode* DDListInit();
//释放内存、销毁空间
void DDListDestory(DDListNode* phead);
//打印
void DDListPrint(DDListNode* phead);
//尾插
void DDListPushBack(DDListNode* phead, DDLTDataType x);
//头插
void DDListPushFront(DDListNode* phead, DDLTDataType x);
//头删
void DDListPopFront(DDListNode* phead);
//尾删
void DDListPopBack(DDListNode* phead);
//查找
DDListNode* DDListFind(DDListNode* phead, DDLTDataType x);
// pos位置之前插入x
void DDListInsert(DDListNode* pos, DDLTDataType x);
// 删除pos位置的值
void DDListErase(DDListNode* pos);
//判空
bool DDListEmpty(DDListNode* phead);
//大小
int DDListSize(DDListNode* phead);

DDList.c:

#include "DDList.h"
//带头双向循环链表

//动态开辟新结点
DDListNode* BuyDDListNode(DDLTDataType x)
{
	DDListNode* newnode = (DDListNode*)malloc(sizeof(DDListNode));
	newnode->data = x;
	newnode->next = NULL;
	newnode->prev = NULL;

	return newnode;
}
//初始化
//为了减少二级指针的使用问题,采用返回赋值的方式解决
DDListNode* DDListInit()
{
	DDListNode* phead = BuyDDListNode(0);
	phead->next = phead;
	phead->prev = phead;

	return phead;
}
//释放内存、销毁空间
void DDListDestory(DDListNode* phead)
{
	assert(phead);
	DDListNode* cur = phead->next;
	while (cur != phead)
	{
		DDListNode* next = cur->next;
		free(cur);
		cur = next;
	}

	free(phead);
	phead = NULL;
}
//打印
void DDListPrint(DDListNode* phead)
{
	assert(phead);

	DDListNode* cur = phead->next;
	while (cur != phead)
	{
		printf("%d ", cur->data);
		cur = cur->next;
	}
	printf("\n");
}
1.尾插
//void DDListPushBack(DDListNode* phead, DDLTDataType x)
//{
//	assert(phead);
//	DDListNode* tail = phead->prev;
//	DDListNode* newnode = BuyDDListNode(x);
//
//	tail->next = newnode;
//	newnode->prev = tail;
//	newnode->next = phead;
//	phead->prev = newnode;
//}
//2.尾插——附用DDListInsert
void DDListPushBack(DDListNode* phead, DDLTDataType x)
{
	assert(phead);
	DDListInsert(phead, x);
}
1.头插
//void DDListPushFront(DDListNode* phead, DDLTDataType x)
//{
//	assert(phead);
//	//写法1.定义first,不用注意链接顺序
//	DDListNode* first = phead->next;
//	DDListNode* newnode = BuyDDListNode(x);
//	// phead newnode first
//	phead->next = newnode;
//	newnode->prev = phead;
//	newnode->next = first;
//	first->prev = newnode;
//
//	/*//写法2.不定义first,要注意链接顺序
//	DDListNode* newnode = BuyDDListNode(x);
//	newnode->next = phead->next;
//	phead->next->prev = newnode;
//	phead->next = newnode;
//	newnode->prev = phead;*/
//}
//2.头插——附用DDListInsert
void DDListPushFront(DDListNode* phead, DDLTDataType x)
{
	assert(phead);
	DDListInsert(phead->next, x);
}
1.头删
//void DDListPopFront(DDListNode* phead)
//{
//	assert(phead);
//	assert(phead->next != phead);
//
//	DDListNode* first = phead->next;
//	DDListNode* second = first->next;
//	phead->next = second;
//	second->prev = phead;
//
//	free(first);
//	first = NULL;
//}
//2.头删——附用DDListErase
void DDListPopFront(DDListNode* phead)
{
	assert(phead);
	DDListErase(phead->next);
}
1.尾删
//void DDListPopBack(DDListNode* phead)
//{
//	assert(phead);
//	assert(phead->next != phead);
//
//	DDListNode* tail = phead->prev;
//	DDListNode* prev = tail->prev;
//
//	prev->next = phead;
//	phead->prev = prev;
//
//	free(tail);
//	tail = NULL;
//}
//2.尾删——附用DDListErase
void DDListPopBack(DDListNode* phead)
{
	assert(phead);
	DDListErase(phead->prev);
}
//查找
DDListNode* DDListFind(DDListNode* phead, DDLTDataType x)
{
	assert(phead);
	DDListNode* cur = phead->next;
	while (cur != phead)
	{
		if (cur->data == x)
		{
			return cur;
		}

		cur = cur->next;
	}

	return NULL;
}

// pos位置之前插入x
void DDListInsert(DDListNode* pos, DDLTDataType x)
{
	assert(pos);
	DDListNode* prev = pos->prev;
	DDListNode* newnode = BuyDDListNode(x);

	// prev newnode pos
	prev->next = newnode;
	newnode->prev = prev;
	newnode->next = pos;
	pos->prev = newnode;
}

// 删除pos位置的值
void DDListErase(DDListNode* pos)
{
	assert(pos);

	DDListNode* prev = pos->prev;
	DDListNode* next = pos->next;
	prev->next = next;
	next->prev = prev;
	free(pos);
}

Test.c:

#include "DDList.h"
//带头双向循环链表

void TestDDList1()
{
	DDListNode* plist = DDListInit();
	DDListPushBack(plist, 1);
	DDListPushBack(plist, 2);
	DDListPushBack(plist, 3);
	DDListPushBack(plist, 4);
	DDListPrint(plist);

	DDListPushFront(plist, 0);
	DDListPushFront(plist, -1);
	DDListPrint(plist);

	DDListPopFront(plist);
	DDListPopFront(plist);
	DDListPopFront(plist);
	DDListPrint(plist);

	DDListPopBack(plist);
	DDListPrint(plist);

	DDListDestory(plist);
}

void TestDDList2()
{
	DDListNode* plist = DDListInit();
	DDListPushBack(plist, 1);
	DDListPushBack(plist, 2);
	DDListPushBack(plist, 3);
	DDListPushBack(plist, 4);
	DDListPrint(plist);

	DDListNode* pos = DDListFind(plist, 3);
	if (pos)
	{
		// 查找,附带着修改的作用
		pos->data *= 10;
		printf("找到了,并且节点的值乘以10\n");
	}
	else
	{
		printf("没有找到\n");
	}

	DDListPrint(plist);

	DDListInsert(pos, 300);
	DDListPrint(plist);

	DDListErase(pos);
	DDListPrint(plist);
}

int main()
{
	TestDDList1();
	TestDDList2();

	return 0;
}

后记:
●由于作者水平有限,文章难免存在谬误之处,敬请读者斧正,俚语成篇,恳望指教!

                                                                       ——By 作者:新晓·故知

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值