0
点赞
收藏
分享

微信扫一扫

带头结点双向循环 -- 双向链表

阎小妍 2022-04-06 阅读 107

目录

一、双向链表初始化

二、尾插

问题1:什么时候传一级指针,什么时候传二级指针呢?

三、打印

四、尾删

五、头插

六、头删

七、pos之前插入

 八、删除pos位置的节点

 总代码:

List.h

List.c

 test.c


一、双向链表初始化

二、尾插

问题1:什么时候传一级指针,什么时候传二级指针呢?

三、打印

四、尾删

五、头插

六、头删

七、pos之前插入

 八、删除pos位置的节点

 总代码:

List.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<assert.h>
typedef int DataType;
typedef struct ListNode
{
	DataType data;
	struct ListNode* next;
	struct ListNode* prev;
}LTNode;

//这次不传二级指针,用返回值
LTNode* InitList();
//尾插
void ListPushBack(LTNode* phead, DataType x);
//尾删
void ListPopBack(LTNode* phead);
//头插
void ListPushFront(LTNode* phead, DataType x);
//头删
void ListPopFront(LTNode* phead);
//查找
LTNode* ListFind(LTNode* phead, DataType x);
//pos位置之前插入
void ListInsert(LTNode* pos, DataType x);
//删除pos位置结点
void ListErase(LTNode* pos);

List.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"List.h"
//增加节点
LTNode* BuyNode(DataType x)
{
	LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));
	if (newnode == NULL)
	{
		printf("newnode failed\n");
		exit(-1);
	}
	newnode->data = x;
	newnode->next = newnode->prev = NULL;
	return newnode;
}
//初始化
LTNode* InitList()
{
	//带头节点,循环链表
	//哨兵位头结点
	LTNode* phead = (LTNode*)malloc(sizeof(LTNode));
	phead->next = phead->prev = phead;
	return phead;
}
//尾插
void ListPushBack(LTNode* phead, DataType x)
{
	assert(phead);
	//LTNode* newnode = BuyNode(x);
	//LTNode* tail = phead->prev;
	//tail->next = newnode;
	//newnode->prev = tail;
	//newnode->next = phead;
	//phead->prev = newnode;
	
	//改写:
	ListInsert(phead,x);
}
//打印
void ListPrint(LTNode* phead)
{
	assert(phead);//如果phead没有初始化,则会为NULL,而带头结点的指针不会为NULL,所以在此断言
	LTNode* cur = phead->next;
	while (cur != phead)
	{
		printf("%d->",cur->data);
		cur = cur->next;
	}
	printf("NULL\n");
}
//尾删
void ListPopBack(LTNode* phead)
{
	assert(phead);
	//暴力判定:头指针的下一个结点还是头结点,那么说明只有头结点
	assert(phead->prev != phead);
	//
	//LTNode* tail = phead->prev;
	//LTNode* tailprev = tail->prev;

	//tailprev->next = phead;
	//phead->prev = tailprev;

	温柔判定:链表为空,也就是只剩头结点时,就不会再删除的情况
	if (tail != phead)
	{
		free(tail);
	}
	tail = NULL;

	//改写:
	ListErase(phead->prev);
}
//头插
void ListPushFront(LTNode* phead, DataType x)
{
	assert(phead);
	/*LTNode* Next = phead->next;
	LTNode* newnode = BuyNode(x);
	phead->next = newnode;
	newnode->prev = phead;
	newnode->next = Next;
	Next->prev = newnode;*/

	//改写:
	ListInsert(phead->next,x);
}
//头删
void ListPopFront(LTNode* phead)
{
	assert(phead);
	//LTNode* tail = phead->next;
	//LTNode* tailnext = tail->next;
	//
	暴力判断:说明只有一个头结点
	//assert(phead->next != phead);
	//
	//phead->next = tailnext;
	//tailnext->prev = phead;
	//free(tail);
	//tail = NULL;

	//改写
	ListErase(phead->next);
}
//查找
LTNode* ListFind(LTNode* phead, DataType x)
{
	assert(phead);
	LTNode* cur = phead->next;
	while (cur != phead)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}
//pos位置之前插入
void ListInsert(LTNode* pos, DataType x)
{
	assert(pos);
	LTNode* posprev = pos->prev;
	LTNode* newnode = BuyNode(x);

	posprev->next = newnode;
	newnode->prev = posprev;

	newnode->next = pos;
	pos->prev = newnode;
}
//删除pos位置结点
void ListErase(LTNode* pos)
{
	assert(pos);
	//因为phead结点不存数据,所以pos不会指向phead,所以不用判断
	
	LTNode* posnext = pos->next;
	LTNode* posprev = pos->prev;
	
	posprev->next = posnext;
	posnext->prev = posprev;
	free(pos);
	pos = NULL;
}

 test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"List.h"

testList1()
{
	LTNode* plist = InitList();
	ListPushBack(plist,1);//因为有头结点,所以不用改变头指针,总结:不改变头指针传一级,改变传二级
	ListPushBack(plist,2);
	ListPushBack(plist,3);
	ListPushBack(plist,4);
	ListPrint(plist);
	
	ListPopBack(plist);
	ListPrint(plist);
	
	ListPopBack(plist);
	ListPrint(plist);
	
	//ListPopBack(plist);
	//ListPushFront(plist,4);
	//ListPrint(plist);

	ListPopFront(plist);
	ListPrint(plist);

	//ListPopFront(plist);
	//ListPopFront(plist);
	//ListPopFront(plist);
	//LTNode* pos = ListFind(plist,3);
	//if (pos != NULL)
	//{
	//	/*printf("%d\n",pos->data);*/
	//	ListInsert(pos, 20);
	//	ListErase(pos);
	//}
	//ListPrint(plist);

}


int main()
{
	testList1();
	return 0;
}

 本文为带头节点双循坏链表,如有问题,请评论区多多评论^_^ 

举报

相关推荐

0 条评论