双向带头链表实现

目录

[一. 逻辑结构图解](#一. 逻辑结构图解)

[1. 节点中存储的值](#1. 节点中存储的值)

2.逻辑实现

[二. 各种功能实现](#二. 各种功能实现)

[1. 创建节点函数](#1. 创建节点函数)

[2. 初始化哨兵位](#2. 初始化哨兵位)

[3. 尾插](#3. 尾插)

[4. 头插](#4. 头插)

[5. 尾删](#5. 尾删)

[6. 头删](#6. 头删)

[7. 打印链表值](#7. 打印链表值)

[8. 查找数据,返回节点地址](#8. 查找数据,返回节点地址)

[9. 指定地址后插入节点](#9. 指定地址后插入节点)

[10. 删除指定地址节点](#10. 删除指定地址节点)

[11. 销毁链表](#11. 销毁链表)

[三. 完整代码](#三. 完整代码)

[1. list.h](#1. list.h)

[2. list.c](#2. list.c)

[3. 测试](#3. 测试)


由于上一篇已经对链表的基本概念讲解完毕,这里就不过多赘述了

一. 逻辑结构图解

1. 节点中存储的值

qrev是上一个节点的地址

data是节点中存储的数据

next是下一个节点的位置

2.逻辑实现

第一个节点为哨兵位不存储数据

二. 各种功能实现

1. 创建节点函数
cpp 复制代码
ListNode* BuyListNode(DataType x)
{
	ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
	if (newnode == NULL)
	{
		exit(-1);
	}
	newnode->data = x;
	newnode->next = newnode->prev = newnode;
	return newnode;
}
2. 初始化哨兵位

由于需要改变哨兵位本身,所以用二级指针

之后就不用改变哨兵位了所以不用用二级指针

cpp 复制代码
void ListNodeInit(ListNode** pphead)
{
	*pphead = BuyListNode(0);
}
3. 尾插
cpp 复制代码
void ListNodePushBack(ListNode* phead, DataType x)
{
	ListNode* tail = phead->prev;
	assert(phead);
	ListNode* newnode = BuyListNode(x);
	newnode->prev = phead->prev;
	newnode->next = phead;

	tail->next = newnode;//之前的尾指向现在的尾
	phead->prev = newnode;//头的上一个改为现在的尾
}
4. 头插
cpp 复制代码
void ListNodePushFront(ListNode* head,DataType x)
{
	assert(head);
	ListNode* first = head->next;
	ListNode* newnode = BuyListNode(x);

	newnode->next = head->next;
	newnode->prev = head;

	first->prev = newnode;

	head->next = newnode;
}
5. 尾删
cpp 复制代码
void ListNodePopBack(ListNode* head)
{
	assert(head);
	ListNode* tail=head->prev;
	ListNode* newtail = tail->prev;
	head->prev = newtail;
	newtail->next = head;
	free(tail);
	tail = NULL;
}
6. 头删
cpp 复制代码
void ListNodePopFront(ListNode* head)
{
	assert(head);
	ListNode* first=head->next;
	ListNode* newfirst = first->next;
	head->next = newfirst;
	newfirst->prev = head;

	free(first);
	first = NULL;
}
7. 打印链表值
cpp 复制代码
void ListNodePrint(ListNode* phead)
{
	assert(phead);
	ListNode* tmp = phead->next;
	while (tmp!= phead)
	{
		printf("%d  ", tmp->data);
		tmp = tmp->next;
	}
}
8. 查找数据,返回节点地址
cpp 复制代码
ListNode* ListNodeFind(ListNode* head,DataType x)
{
	assert(head);
	ListNode* tmp = head->next;
	while (tmp!=head)
	{
		if (tmp->data == x)
			return tmp;
		tmp = tmp->next;
	}
	return NULL;
}
9. 指定地址后插入节点
cpp 复制代码
void ListNodeInsert(ListNode* pos, DataType x)
{
	assert(pos);
	ListNode* newnext = pos->next;
	ListNode* newnode = BuyListNode(x);

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

}
10. 删除指定地址节点
cpp 复制代码
void ListNodeErase(ListNode* pos)
{
	assert(pos);
	ListNode* posprev = pos->prev, * posnext = pos->next;
	posprev->next = posnext;
	posnext->prev = posprev;
	free(pos);
	pos = NULL;
}
11. 销毁链表
cpp 复制代码
void ListNodeDestroy(ListNode* head)
{
	assert(head);
	ListNode* cur = head->next;
	while (cur != head)
	{
		ListNode* next = cur->next;
		free(cur);
		cur = next;
	}
}

三. 完整代码

1. list.h
cpp 复制代码
#define _CRT_SECURE_NO_WARNINGS h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>

typedef int DataType;

typedef struct ListNode
{
	DataType data;
	struct SList* next;
	struct SList* prev;
}ListNode;

//初始化
void ListNodeInit(ListNode** pphead);
//尾插
void ListNodePushBack(ListNode* head, DataType x);
//打印链表
void ListNodePrint(ListNode* phead);
//头插
void ListNodePushFront(ListNode* head, DataType x);
//尾删
void ListNodePopBack(ListNode* head);
//头删
void ListNodePopFront(ListNode* head);
//查找数据
ListNode* ListNodeFind(ListNode* head, DataType x);
//指定位置后插入
void ListNodeInsert(ListNode* pos, DataType x);
//指定位置删除
void ListNodeErase(ListNode* pos);
//销毁链表
void ListNodeDestroy(ListNode* head);
2. list.c
cpp 复制代码
#define _CRT_SECURE_NO_WARNINGS h

#include"list.h"

ListNode* BuyListNode(DataType x)
{
	ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
	if (newnode == NULL)
	{
		exit(-1);
	}
	newnode->data = x;
	newnode->next = newnode->prev = newnode;
	return newnode;
}

void ListNodeInit(ListNode** pphead)
{
	*pphead = BuyListNode(0);
}

void ListNodePushBack(ListNode* phead, DataType x)
{
	ListNode* tail = phead->prev;
	assert(phead);
	ListNode* newnode = BuyListNode(x);
	newnode->prev = phead->prev;
	newnode->next = phead;

	tail->next = newnode;//之前的尾指向现在的尾
	phead->prev = newnode;//头的上一个改为现在的尾
}

void ListNodePrint(ListNode* phead)
{
	assert(phead);
	ListNode* tmp = phead->next;
	while (tmp!= phead)
	{
		printf("%d  ", tmp->data);
		tmp = tmp->next;
	}
}

void ListNodePushFront(ListNode* head,DataType x)
{
	assert(head);
	ListNode* first = head->next;
	ListNode* newnode = BuyListNode(x);

	newnode->next = head->next;
	newnode->prev = head;

	first->prev = newnode;

	head->next = newnode;
}

void ListNodePopBack(ListNode* head)
{
	assert(head);
	ListNode* tail=head->prev;
	ListNode* newtail = tail->prev;
	head->prev = newtail;
	newtail->next = head;
	free(tail);
	tail = NULL;
}

void ListNodePopFront(ListNode* head)
{
	assert(head);
	ListNode* first=head->next;
	ListNode* newfirst = first->next;
	head->next = newfirst;
	newfirst->prev = head;

	free(first);
	first = NULL;
}

ListNode* ListNodeFind(ListNode* head,DataType x)
{
	assert(head);
	ListNode* tmp = head->next;
	while (tmp!=head)
	{
		if (tmp->data == x)
			return tmp;
		tmp = tmp->next;
	}
	return NULL;
}

void ListNodeInsert(ListNode* pos, DataType x)
{
	assert(pos);
	ListNode* newnext = pos->next;
	ListNode* newnode = BuyListNode(x);

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

}

void ListNodeErase(ListNode* pos)
{
	assert(pos);
	ListNode* posprev = pos->prev, * posnext = pos->next;
	posprev->next = posnext;
	posnext->prev = posprev;
	free(pos);
	pos = NULL;
}

void ListNodeDestroy(ListNode* head)
{
	assert(head);
	ListNode* cur = head->next;
	while (cur != head)
	{
		ListNode* next = cur->next;
		free(cur);
		cur = next;
	}
}
3. 测试
cpp 复制代码
#define _CRT_SECURE_NO_WARNINGS h

#include"list.h"
void test()
{
	ListNode* head=NULL;
	ListNodeInit(&head);
	ListNodePushBack(head, 2);
	ListNodePushBack(head, 45);
	ListNodePushBack(head, 33);
	ListNodePushFront(head, 22);
	ListNodePushFront(head, 66);
	ListNode* find=ListNodeFind(head,33);
	ListNodeInsert(find, 666);
	ListNodePrint(head);
	printf("\n");
	//ListNodePopBack(head);
	ListNodeErase(find);
	ListNodePopFront(head);
	ListNodePrint(head);

}

int main()
{
	test();
}

感谢大家观看,希望可以帮到您

(づ ̄3 ̄)づ╭❤~

相关推荐
一点媛艺31 分钟前
Kotlin函数由易到难
开发语言·python·kotlin
姑苏风35 分钟前
《Kotlin实战》-附录
android·开发语言·kotlin
奋斗的小花生2 小时前
c++ 多态性
开发语言·c++
魔道不误砍柴功2 小时前
Java 中如何巧妙应用 Function 让方法复用性更强
java·开发语言·python
pianmian12 小时前
python数据结构基础(7)
数据结构·算法
闲晨2 小时前
C++ 继承:代码传承的魔法棒,开启奇幻编程之旅
java·c语言·开发语言·c++·经验分享
老猿讲编程2 小时前
一个例子来说明Ada语言的实时性支持
开发语言·ada
UestcXiye3 小时前
《TCP/IP网络编程》学习笔记 | Chapter 3:地址族与数据序列
c++·计算机网络·ip·tcp
Chrikk3 小时前
Go-性能调优实战案例
开发语言·后端·golang
幼儿园老大*3 小时前
Go的环境搭建以及GoLand安装教程
开发语言·经验分享·后端·golang·go