数据结构—双向链表

结构


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

实现双向链表

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;
}

顺序表和链表的分析

相关推荐
南玖yy2 分钟前
C/C++ 内存管理深度解析:从内存分布到实践应用(malloc和new,free和delete的对比与使用,定位 new )
c语言·开发语言·c++·笔记·后端·游戏引擎·课程设计
xindafu32 分钟前
代码随想录算法训练营第三十八天|动态规划part6(完全背包2)
算法·动态规划
刃神太酷啦1 小时前
类和对象(1)--《Hello C++ Wrold!》(3)--(C/C++)
java·c语言·c++·git·算法·leetcode·github
HY小海2 小时前
【数据结构】双链表
c语言·开发语言·数据结构·学习
I AM_SUN2 小时前
994. 腐烂的橘子
数据结构·c++·算法·leetcode·职场和发展
真的想上岸啊3 小时前
c语言第一个小游戏:贪吃蛇小游戏03
c语言·开发语言·算法
bai_lan_ya3 小时前
数据结构之串
数据结构
小狗祈祷诗3 小时前
day18-数据结构引言
c语言·数据结构
真的想上岸啊3 小时前
c语言第一个小游戏:贪吃蛇小游戏01
c语言·开发语言
序属秋秋秋3 小时前
《数据结构初阶》【堆 + 堆排序 + TOP-K】
c语言·数据结构·c++·笔记