初阶数据结构的实现2 双向链表

1.双向链表

1.1 概念与结构

1.2实现双向链表

1.2.1定义程序目标

c 复制代码
#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
typedef int LTDateType;
//定义双向链表结构
typedef struct ListNode {
	LTDateType data;
	ListNode* prev;
	ListNode* next;
}ListNode;
//
ListNode* BuyNode(LTDateType x);
//初始化
void LTInitialise(ListNode** pphead);
//销毁
void LTDestroy(ListNode** pphead);
//尾插
void LTPushBack(ListNode* phead, LTDateType x);
//头插
void LTPushFront(ListNode* phead, LTDateType x);
//打印双向链表
void LTPrint(ListNode* phead);
//判断链表是否为空
bool LTEmpty(ListNode* phead);
//尾删
void PopBack(ListNode* phead);
//头删 
void PopFront(ListNode* phead);
//在pos后插入结点
void LTInsert(ListNode* pos, LTDateType x);
//删除指定位置的结点
void LTEraser(ListNode* pos);

1.2.2 设计程序

面向程序员自身的,能实现包括链表的结构定义、初始化、插入、删除、查找、遍历、排序等操作

1.2.3编写代码

c 复制代码
#define _CRT_SECURE_NO_WARNINGS 1
#include"list.h"
ListNode* BuyNode(LTDateType x)
{
	ListNode* NewNode = malloc(sizeof(ListNode));
	if (NewNode == NULL)
	{
		perror("Malloc Fail!");
		exit(1);
	}
	NewNode->data = x;
	NewNode->next = NewNode->prev = NewNode;
}

void LTInitialise(ListNode** pphead)
{
	//创建一个头结点(哨兵卫)
	*pphead = BuyNode(-1);
}
//ListNode* LTInitialise()
//{
//	return BuyNode(-1);
//}
void LTDestory(ListNode** pphead)
{
	assert(*pphead && pphead);
	ListNode*pcur = (*pphead)->next;
	while (pcur!=*pphead)
	{
		ListNode* Next = pcur->next;
		free(pcur);
		pcur = Next;
	}
	free(*pphead);
	*pphead = NULL;
	pcur = NULL;
}
//void LTDestory(ListNode* phead)
//{
//	assert(phead);
//	ListNode* pcur = phead->next;
//	while (pcur != phead)
//	{
//		ListNode* Next = pcur->next;
//		free(pcur);
//		pcur = Next;
//	}
//	free(phead);
//	phead = NULL;
//	pcur = NULL;//实参手动置为空或者重新封装一个函数
//}
void LTPushBack(ListNode* phead, LTDateType x)
{
	assert(phead);
	ListNode* NewNode = BuyNode(x);
	NewNode->next = phead;
	NewNode->prev = phead->prev;
	phead->prev->next = NewNode;
	phead->prev = NewNode;
}

void LTPushFront(ListNode* phead, LTDateType x)
{
	assert(phead);
	ListNode* NewNode = BuyNode(x);
	NewNode->prev = phead;
	NewNode->next = phead->next;
	phead->next->prev = NewNode;
}

//打印双向链表
void LTPrint(ListNode* phead)
{
	ListNode* pcur = phead->next;
	while (pcur != phead)
	{
		printf("%d->", pcur->data);
		pcur = pcur->next;
	}
	printf("\n");
}

bool LTEmpty(ListNode* phead)
{
	if (phead->next == phead)
		return false;
	else
		return true;
}

void PopBack(ListNode* phead)
{
	assert(phead);
	assert(LTEmpty(phead));
	ListNode* del = phead->prev;
	ListNode* prev = del->prev;
	prev->next = phead;
	phead->prev = prev;
	free(del);
	del = NULL;
}

void PopFront(ListNode* phead)
{
	assert(phead);
	assert(LTEmpty(phead));
	ListNode* del = phead->next;
	ListNode* Next = del->next;
	Next->prev = phead;
	phead->next = Next;
	free(del);
	del = NULL;
}

ListNode* LTFind(ListNode* phead, LTDateType x)
{
	ListNode* pcur = phead->next;
	while (pcur != phead)
	{
		if (pcur->data == x)
		{
			return pcur;
		}
		pcur = pcur->next;
	}
	return NULL;
}

void LTInsert(ListNode* pos,LTDateType x)
{
	assert(pos);
	ListNode* NewNode = BuyNode(x);
	NewNode->next = pos->next;
	NewNode->prev = pos;
	pos->next->prev = NewNode;
	pos->next = NewNode;
}
void LTEraser(ListNode* pos)
{
	assert(pos);
	pos->prev->next = pos->next;
	pos->next->prev = pos->prev;

	free(pos);
	pos = NULL;
}

1.2.3测试和调试代码

c 复制代码
#define _CRT_SECURE_NO_WARNINGS 1
#include"List.h"

void ListTest01()
{
	//创建双向链表变量
	ListNode* plist = NULL;
	LTInitialise(&plist);

	/*ListNode* plist = LTInit();*/

	LTPushBack(plist, 1);
	LTPushBack(plist, 2);
	LTPushBack(plist, 3);
	LTPushBack(plist, 4);
	LTPrint(plist);
	LTPushFront(plist, 1);
	LTPrint(plist);
	LTPushFront(plist, 2);
	LTPrint(plist);
	LTPushFront(plist, 3);
	LTPrint(plist);
	LTPushFront(plist, 4);
	LTPrint(plist);
	
	LTPopBack(plist);
	LTPrint(plist);
	LTPopBack(plist);
	LTPrint(plist);
	LTPopBack(plist);
	LTPrint(plist);
	LTPopBack(plist);
	LTPrint(plist);
	LTPopBack(plist);
	LTPrint(plist);
	/*LTPopFront(plist);
	LTPrint(plist);
	LTPopFront(plist);
	LTPrint(plist);
	LTPopFront(plist);
	LTPrint(plist);
	LTPopFront(plist);
	LTPrint(plist);
	LTPopFront(plist);
	LTPrint(plist);*/

	ListNode* pos = LTFind(plist, 3);
	if (pos == NULL)
	{
		printf("没有找到!\n");
	}
	else
	{
		printf("找到了!\n");
	}
	LTInsert(pos, 11);
	LTPrint(plist);
	LTErase(pos);
	LTPrint(plist);

	LTDestroy(&plist);
	/*LTDestroy2(plist);*/
	plist = NULL;
}
int main()
{
	ListTest01();
	return 0;
}
相关推荐
Dong雨2 分钟前
六大排序算法:插入排序、希尔排序、选择排序、冒泡排序、堆排序、快速排序
数据结构·算法·排序算法
茶猫_32 分钟前
力扣面试题 39 - 三步问题 C语言解法
c语言·数据结构·算法·leetcode·职场和发展
初学者丶一起加油34 分钟前
C语言基础:指针(数组指针与指针数组)
linux·c语言·开发语言·数据结构·c++·算法·visual studio
半盏茶香2 小时前
C语言勘破之路-最终篇 —— 预处理(上)
c语言·开发语言·数据结构·c++·算法
2401_858286112 小时前
118.【C语言】数据结构之排序(堆排序和冒泡排序)
c语言·数据结构·算法
没事就去码2 小时前
RBTree(红黑树)
数据结构·c++
就爱学编程3 小时前
重生之我在异世界学编程之数据结构与算法:单链表篇
数据结构·算法·链表
CSCN新手听安8 小时前
list的常用操作
数据结构·list
梅茜Mercy10 小时前
数据结构:链表(经典算法例题)详解
数据结构·链表
青春男大10 小时前
java栈--数据结构
java·开发语言·数据结构·学习·eclipse