双向带头链表实现

目录

一. 逻辑结构图解

1. 节点中存储的值

 2.逻辑实现

二. 各种功能实现

1. 创建节点函数

2. 初始化哨兵位

3. 尾插

4. 头插

5. 尾删

6. 头删

7. 打印链表值

8. 查找数据,返回节点地址

9. 指定地址后插入节点

10. 删除指定地址节点

11. 销毁链表

三. 完整代码

1. list.h

2. list.c

3. 测试


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

一. 逻辑结构图解

1. 节点中存储的值

qrev是上一个节点的地址

data是节点中存储的数据

next是下一个节点的位置

 2.逻辑实现

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

二. 各种功能实现

1. 创建节点函数
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. 初始化哨兵位

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

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

void ListNodeInit(ListNode** pphead)
{
	*pphead = BuyListNode(0);
}
3. 尾插
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. 头插
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. 尾删
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. 头删
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. 打印链表值
void ListNodePrint(ListNode* phead)
{
	assert(phead);
	ListNode* tmp = phead->next;
	while (tmp!= phead)
	{
		printf("%d  ", tmp->data);
		tmp = tmp->next;
	}
}
8. 查找数据,返回节点地址
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. 指定地址后插入节点
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. 删除指定地址节点
void ListNodeErase(ListNode* pos)
{
	assert(pos);
	ListNode* posprev = pos->prev, * posnext = pos->next;
	posprev->next = posnext;
	posnext->prev = posprev;
	free(pos);
	pos = NULL;
}
11. 销毁链表
void ListNodeDestroy(ListNode* head)
{
	assert(head);
	ListNode* cur = head->next;
	while (cur != head)
	{
		ListNode* next = cur->next;
		free(cur);
		cur = next;
	}
}

三. 完整代码

1. list.h
#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
#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. 测试
#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 ̄)づ╭❤~

评论 25
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值