数据结构—双向链表

结构


带头链表里的头结点,实际为"哨兵位",哨兵位结点不存储任何有效元素,只是站在这里"放哨
的"

实现双向链表

List.h

cpp 复制代码
#pragma once

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>

//定义双向链表结点的结构
typedef int LTDataType;
typedef struct ListNode
{
	int data;
	struct ListNode* next;
	struct ListNode* prev;

}LTNode;


//初始化
//void LTInit(LTNode** pphead);
LTNode* LTInit();

void LTPrint(LTNode* phead);

//插入
//1.传一级还是二级,要看pphead指向的结点会不会发生改变
//2.如果发生改变,那么pphead的改变要影响实参,传二级
//3.如果不发生改变,pphead不会影响实参,传一级
void LTPushBack(LTNode* phead, LTDataType x);
void LTPushFront(LTNode* phead, LTDataType x);

//删除
void LTPopBack(LTNode* phead);
void LTPopFront(LTNode* phead);

bool LTEmpty(LTNode* phead);


//查找
LTNode* LTFind(LTNode* phead, LTDataType x);

//在pos位置之后插入结点 
void LTInsert(LTNode* pos, LTDataType x);
//删除指定位置的结点
void LTErase(LTNode* pos);
//销毁
void LTDesTroy(LTNode** pphead);

//为了保持接口的一致性,优化接口都为一级指针
void LTDesTroy2(LTNode* phead);

List.c

cpp 复制代码
#include"List.h"
LTNode* LTBuyNode(LTDataType x)
{
	LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
			exit(1);
	}
	newnode->data = x;
	newnode->next = newnode->prev = newnode;
}
//初始化
//void LTInit(LTNode** pphead)
//{
//	//创建一个头结点(哨兵位)
//	*pphead = LTBuyNode(-1);
//
//}

LTNode* LTInit()
{
	LTNode* phead = LTBuyNode(-1);
	return phead;
}

void LTPushBack(LTNode* phead, LTDataType x)
{
	assert(phead);
	LTNode* newnode = LTBuyNode(x);
	newnode->next = phead;
	newnode->prev = phead->prev;

	phead->prev->next = newnode;
	phead->prev = newnode;
}

void LTPushFront(LTNode* phead, LTDataType x)
{
	assert(phead);

	LTNode* newnode = LTBuyNode(x);

	newnode->next = phead->next;
	newnode->prev = phead;
	
	phead->next->prev = newnode;
	phead->next = newnode;
}

void LTPrint(LTNode* phead)
{
	LTNode* pcur = phead->next;
	while (pcur!=phead)
	{
		printf("%d->", pcur->data);
		pcur = pcur->next;
	}
	printf("\n");
}

bool LTEmpty(LTNode* phead)
{
	assert(phead);
	return phead->next == phead; 
}


void LTPopBack(LTNode* phead)
{
	assert(phead);
	assert(!LTEmpty(phead));

	LTNode* del = phead->prev;
	LTNode* prev = del->prev;

	prev->next = phead;
	phead->prev = prev;

	free(del);
	del = NULL;
}

void LTPopFront(LTNode* phead)
{
	assert(phead);
	assert(!LTEmpty(phead));

	LTNode* del = phead->next;
	del->next->prev = phead;
	phead->next = del->next; 
	free(del);
	del = NULL;

}


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

void LTInsert(LTNode* pos, LTDataType x)
{
	assert(pos);

	LTNode* newnode = LTBuyNode(x);

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

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


void LTErase(LTNode* pos)
{
	assert(pos);
	pos->prev->next = pos->next;
	pos->next->prev = pos->prev;

	free(pos);
	pos = NULL;
}


void LTDesTroy(LTNode** pphead)
{
	assert(pphead && *pphead);
	LTNode* pcur = (*pphead)->next;
	while (pcur!=*pphead)
	{
		LTNode* Next = pcur->next;
		free(pcur);
		pcur = Next; 
	}
	
	 //销毁哨兵位结点
	free(*pphead);
	*pphead = NULL;
	pcur = NULL;
}


void LTDesTroy2(LTNode* phead)
{
	assert(phead);
	LTNode* pcur = phead->next;
	while (pcur != phead)
	{
		LTNode* Next = pcur->next;
		free(pcur);
		pcur = Next;
	}
	free(phead);
	phead = pcur = NULL;
}

test.c

cpp 复制代码
#include"List.h"

void ListTest01()
{
	//创建双向链表
	/*LTNode* plist = NULL;
	LTInit(&plist);*/

    LTNode*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);*/



	/*LTPopFront(plist);
	LTPrint(plist);
	LTPopFront(plist);
	LTPrint(plist);
	LTPopFront(plist);
	LTPrint(plist);
	LTPopFront(plist);
	LTPrint(plist);*/

	//LTNode* pos = LTFind(plist, 2);
	/*if (pos == NULL)
	{
		printf("没有找到!\n");
	}
	else
	{
		printf("找到了!\n");
	}*/


	/*LTInsert(pos, 13);
	LTPrint(plist);*/


	/*LTErase(pos);
	LTPrint(plist);*/

	//LTDesTroy(&plist);
	LTDesTroy2(plist);
}


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

顺序表和链表的分析

相关推荐
W23035765735 小时前
经典算法:最长上升子序列(LIS)深度解析 C++ 实现
开发语言·c++·算法
.Ashy.5 小时前
2026.4.11 蓝桥杯软件类C/C++ G组山东省赛 小记
c语言·c++·蓝桥杯
2401_892070985 小时前
链栈(链式栈) 超详细实现(C 语言 + 逐行精讲)
c语言·数据结构·链栈
minji...6 小时前
Linux 线程同步与互斥(三) 生产者消费者模型,基于阻塞队列的生产者消费者模型的代码实现
linux·运维·服务器·开发语言·网络·c++·算法
语戚7 小时前
力扣 968. 监控二叉树 —— 贪心 & 树形 DP 双解法递归 + 非递归全解(Java 实现)
java·算法·leetcode·贪心算法·动态规划·力扣·
skywalker_117 小时前
力扣hot100-7(接雨水),8(无重复字符的最长子串)
算法·leetcode·职场和发展
bIo7lyA8v8 小时前
算法稳定性分析中的输入扰动建模的技术9
算法
CoderCodingNo8 小时前
【GESP】C++三级真题 luogu-B4499, [GESP202603 三级] 二进制回文串
数据结构·c++·算法
sinat_286945198 小时前
AI Coding 时代的 TDD:从理念到工程落地
人工智能·深度学习·算法·tdd