数据结构-双向循环链表的尾插尾删 具体位置插入和删除操作

双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。

直接上代码
下面是DouLsit.h

#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>

typedef int DataType;
typedef struct ListNode
{
	DataType Data; // 数据域
	struct ListNode* next; // 后继
	struct ListNode* prior; // 前驱
}ListNode;

void ListInit(ListNode** pphead); // 初始化一个头结点
ListNode* CreatListNode(DataType x); // 创建一个新结点
void Listprint(ListNode* phead); // 打印链表
void ListPushBack(ListNode* phead, DataType x); // 链表尾插
void ListPopBack(ListNode* phead); // 尾删
void ListInsert(ListNode* phead, int pos, DataType x); // 具体位置插入不适用尾插
void ListDelete(ListNode* phead, int pos, DataType* x); // 具体位置删除
void DestoryList(ListNode** pphead); // 销毁链表

下面是DouList.c

#include "DouList.h"

void ListInit(ListNode** pphead) 
{
	*pphead = CreatListNode(0); // 数据域为0
	(*pphead)->prior = *pphead; // 构成前驱循环结点
	(*pphead)->next = *pphead; // 构成后继循环结点
}

ListNode* CreatListNode(DataType x) 
{
	ListNode* Node = (ListNode*)malloc(sizeof(ListNode));
	if (Node == NULL)
		exit(-1);
	Node->next = NULL; // 初始化新结点
	Node->prior = NULL;
	Node->Data = x;

	return Node;
}

void Listprint(ListNode* phead)
{
	assert(phead);

	ListNode* cur = phead->next;
	while (cur != phead) // 找到指向头结点的结点
	{
		printf("%d->", cur->Data);
		cur = cur->next;
	}
	printf("\n");
}

void ListPushBack(ListNode* phead, DataType x)
{
	assert(phead);

	ListNode* tail = phead->prior;
	ListNode* newnode = CreatListNode(x);

	tail->next = newnode; // 尾结点指向新结点
	newnode->prior = tail; // 新结点的前驱指向尾结点

	newnode->next = phead; // 新结点后继为头结点
	phead->prior = newnode; // 头结点前驱为新结点
}

void ListPopBack(ListNode* phead)
{
	assert(phead);
	assert(phead->next != phead);

	ListNode* tail = phead->prior; // 尾结点
	ListNode* prev = tail->prior; // 尾结点的前一个结点

	prev->next = phead; // 尾结点后继指向头结点
	phead->prior = prev; // 头结点前驱指向尾结点前一个
	free(tail);
}

void ListInsert(ListNode* phead, int pos, DataType x)
{
	assert(phead);

	ListNode* cur = phead->next; // 有值的结点
	ListNode* newnode = CreatListNode(x);
	ListNode* prev = phead;

	int curpos = 1;
	while (cur->next != phead && curpos < pos) // 找到要插入位置和前一个结点
	{
		prev = cur;
		cur = cur->next;
		curpos++;
	}
	if (pos != curpos) // 插入位置不符合要求
	{
		printf("输入的位置有问题!\n");
		exit(-1);
	}
	cur->prior = newnode; // 新结点插入操作
	newnode->next = cur;

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

void ListDelete(ListNode* phead, int pos, DataType* x)
{
	assert(phead);

	ListNode* cur = phead->next; // 有值的结点
	ListNode* prev = phead;
	int curpos = 1;
	while (cur->next != phead && curpos < pos) // 找到要插入位置和前一个结点
	{
		prev = cur;
		cur = cur->next;
		curpos++;
	}
	if (pos != curpos) // 插入位置不符合要求
	{
		printf("删除的位置有问题!\n");
		exit(-1);
	}
	*x = cur->Data; // 接收删除元素值
	prev->next = cur->next; // 删除元素操作
	cur->next->prior = prev;

	free(cur);
}

void DestoryList(ListNode** pphead)
{
	ListNode* tail = (*pphead)->prior;
	ListNode* Destory = NULL;
	while (tail->prior != *pphead)
	{
		Destory = tail;
		tail = tail->next;
		free(Destory);
		Destory = NULL;
	}
}
int main()
{
	ListNode* DouList = NULL;
	DataType Elem = 0;
	ListInit(&DouList);
	ListPushBack(DouList, 1);
	ListPushBack(DouList, 2);
	ListPushBack(DouList, 3);
	ListPushBack(DouList, 4);
	ListPushBack(DouList, 5);
	ListInsert(DouList, 2, 3);
	ListDelete(DouList, 1, &Elem);
	printf("删除的元素为:%d\n", Elem);
	Listprint(DouList);
}

在这里插入图片描述

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT自习小空间

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值