0
点赞
收藏
分享

微信扫一扫

双向-带头--循环链表

洛茄 2022-03-23 阅读 67

文章目录

先看看头文件

根据头文件来写出各个函数


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

typedef int LTDataType;

typedef struct ListNode
{
	LTDataType data;
	struct ListNode* next;
	struct ListNode* pre;
}ListNode;


//初始化
ListNode* InitListNode();

//创建一个节点
ListNode* BuyListNode(LTDataType x);

//尾插
void ListPushBack(ListNode* phead,LTDataType x);
//尾删
void ListPopBack(ListNode* phead);

//头插
void ListPushFront(ListNode* phead,LTDataType x);
//头删
void ListPopFront(ListNode* phead);

//查找
ListNode* ListFind(ListNode* phead, LTDataType x);

//删除pos位置的值
void ListErase(ListNode* phead, ListNode* pos);

//在pos位置前添加元素
void ListInsertFront(ListNode* phead, ListNode* pos, LTDataType x);

//打印
void Listprint(ListNode* phead);

看完之后大家之后肯定有一个疑惑?这个头插头删尾插尾删为什么传的都是一级指针?
这里涉及的是带头(带哨兵位)和不带头两种情况
看图的解释:
在这里插入图片描述

初始化和创建节点

ListNode* BuyListNode(LTDataType x)
{
	ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
	if (newnode == NULL)
	{
		printf("创建节点失败\n");
		exit(-1);
	}
	newnode->data = x;
	newnode->next = NULL;
	newnode->pre = NULL;

	return newnode;
}

ListNode* InitListNode()
{
	ListNode* phead = BuyListNode(0);
	phead->next = phead;   
	phead->pre = phead;
	return phead;
}

只有头(初始化)
在这里插入图片描述

尾插/尾删

void ListPushBack(ListNode* phead, LTDataType x)
{
	ListNode* newnode = BuyListNode(x);

	ListNode* tail = phead->pre;  //找到尾

	tail->next = newnode;       //先连接尾和newnode
	newnode->pre = tail;  

	newnode->next = phead;     //在连接头和newndoe
	phead->pre = newnode;
}

void ListPopBack(ListNode* phead)
{
	assert(phead);
	if (phead->next == phead)
	{
		printf("没有节点可以删除\n");
		return;
	}

	ListNode* tail = phead->pre;  //找尾
	ListNode* pretail = tail->pre;  //找尾的前一个
	pretail->next = phead;    /将尾的前一个和头连接
	phead->pre = pretail;

	free(tail);
}

头插和头删

void ListPushFront(ListNode* phead, LTDataType x)
{
   //头插
	assert(phead);
	ListNode* newnode = BuyListNode(x);

	ListNode* save = phead->next;  //保存还没插入时的第一个节点
	
	newnode->next = save;     //要插入的接点和第一个连接
	save->pre = newnode;

	phead->next = newnode;   //要插入的节点和头连接
	newnode->pre = phead;

}

void ListPopFront(ListNode* phead)
{
	assert(phead);
	if (phead->next == phead)
	{
		printf("没有可以的删除的元素啦\n");
		return;
	}

	ListNode* save = phead->next;  //第一个节点,要删除的节点
 
	phead->next = save->next;   //连接头和第二个节点==》》就是删除第一个节点
	save->next->pre = phead;

	free(save);
}

查找pos

ListNode* ListFind(ListNode* phead, LTDataType x)
{
	assert(phead);

	ListNode* cur = phead->next;
	while (cur != phead)   //cur等于头的时候就是找完了
	{
		if (cur->data == x)
			return cur;
		cur = cur->next;
	}
	printf("找不到\n");
}

删除pos位置的节点

void ListErase(ListNode* phead, ListNode* pos)
{
	assert(phead && pos);
	ListNode* prepos = pos->pre;   //记录pos位置的前一个和后一个节点
	ListNode* nextpos = pos->next;

	prepos->next = nextpos;   //将pos的前一个和后一个连接---》》就是删除pos了
	nextpos->pre = prepos;
	free(pos);
}

在pos位置前插入元素

void ListInsertFront(ListNode* phead, ListNode* pos, LTDataType x)
{
	assert(phead && pos);
	ListNode* newnode = BuyListNode(x);
    
	ListNode* prepos = pos->pre;    //记录一下pos前一个节点
	
	newnode->next = pos;      //连接要插入的节点和pos位置的节点
	pos->pre = newnode;

	prepos->next = newnode;    //连接要插入的和pos前一个节点
	newnode->pre = prepos;
}
举报

相关推荐

0 条评论