C语言:链表 -2(双链表)

头文件:list.h

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

/*
	声明双链表节点元素
*/
typedef struct LIST_NODE
{
	int value;
	struct LIST_NODE *per;//向前指针	
	struct LIST_NODE *next;//向后指针
}node;

/*
 声明 双链表头尾结构
*/
typedef struct LinkNode
{
	node* head;//指向头部
	node* tail;//指向尾部
}List;


//初始化链表
void init(List *pList);
//头部插入数据
void addOfHead(List* pList, int value);
//尾部插入数据
void addOfBack(List* pList, int value);
//正序输出
void showPositive(List* pList);
//逆序输出
void showReversed(List* pList);
//正序查找
node *findPositive(List* pList,int data);
//逆序查找
node *findReversed(List* pList,int data);
//插入数据
void insertData(List* pList, int value, int newValue);
//删除数据
void deleteData(List* pList, int value);

头文件函数实现:list.c

#include"list.h"

//初始化链表
void init(List* pList)
{
	/*
	 头尾指针初始化NULL
	*/
	pList->head=pList->tail = NULL;
}

//头部插入数据
void addOfHead(List* pList, int value)
{
	//创建节点
	node* pNewNode = malloc(sizeof(node));
	if (pNewNode != NULL)
	{
		pNewNode->value = value;
		pNewNode->per = NULL;
		pNewNode->next = NULL;

		if (pList->head == NULL || pList->tail == NULL)//没有节点
		{
			pList->head = pNewNode;
			pList->tail = pNewNode;
		}
		else//有节点
		{
			pList->head->per = pNewNode;//前 原理的前节点指向新节点
			pNewNode->next = pList->head;//后 新节点的后节点指向原理的头节点
			pList->head = pNewNode;//改变头指针 指向新节点
		}
	}
	
}

//尾部插入数据
void addOfBack(List* pList, int value)
{
	//创建节点
	node* pNewNode = malloc(sizeof(node));
	if (pNewNode != NULL)
	{
		pNewNode->value = value;
		pNewNode->per = NULL;
		pNewNode->next = NULL;

		if (pList->head == NULL || pList->tail == NULL)//没有节点
		{
			pList->head = pNewNode;
			pList->tail = pNewNode;
		}
		else//有节点
		{
			pList->tail->next = pNewNode;//前 原理的后节点指向新节点
			pNewNode->per = pList->tail;//后 新节点的前节点指向原理的尾节点
			pList->tail = pNewNode;//改变尾指针 指向新节点
		}
	}
}

//正序输出
void showPositive(List* pList)
{
	node* p = pList->head;//指向链表结构头节点
	while (p!=NULL)
	{
		printf("%3d", p->value);
		p = p->next;//后指针递增
	}
	printf("\n");
}

//逆序输出
void showReversed(List* pList)
{
	node* p = pList->tail;//指向链表结构尾节点
	while (p != NULL)
	{
		printf("%3d", p->value);
		p = p->per;//前指针递增
	}
	printf("\n");
}
//正序查找
node* findPositive(List* pList, int data)
{
	node* pNode = pList->head;//指向链表结构尾节点
	while (pNode != NULL)
	{
		if (pNode->value == data)
		{
			return pNode;
		}
		pNode = pNode->next;//后指针递增
	}
	return NULL;
}
//逆序查找
node* findReversed(List* pList, int data)
{
	node* pNode = pList->tail;//指向链表结构尾节点
	while (pNode != NULL)
	{
		if (pNode->value == data)
		{
			return pNode;
		}
		pNode = pNode->per;//前指针递增
	}
	return NULL;
}

/*
	插入数据			insertData
	参数:			List* pList		链表
					int value		要插入数据的毗邻数据值,确定插入位置,如果 value 在中间则插入其前,若是头部,则插入插入头			  部,若是尾部,则插入尾部
					int newValue	要插入的新节点的值
*/
void insertData(List* pList, int value,int newValue)
{
	node* pNewNode = malloc(sizeof(node));
	if (pNewNode != NULL)
	{
		pNewNode->value = newValue;
		pNewNode->per = NULL;
		pNewNode->next = NULL;

		//查找元素
		node* p = NULL;
		p = pList->head;
		while (p != NULL)
		{
			if (p->value == value)
			{
				break;//找到匹配的值,跳出循环
			}
			else
			{
				p = p->next;//指针向前递增
			}
		}

		//p存储了匹配值的指针
		if (p != NULL)
		{
			if (p != pList->head || p == pList->tail)//匹配在链表中间或尾部,在匹配元素的前面插入
			{
				pNewNode->next = p; //向后指针 指向匹配的元素
				pNewNode->per = p->per;//向前指针 指向匹配元素的 向前指针 
				p->per->next = pNewNode;//p->per->next 匹配元素的 前一个元素的 向后指针 ,指向新节点
				p->per = pNewNode;//匹配元素的 向前指针 指向新节点
			}
			else if (p == pList->head)//匹配在链表头部,在匹配元素的前面插入
			{
				p->per = pNewNode;//匹配元素的 向前指针 指向新节点
				pNewNode->next = p;
				pList->head = pNewNode;
			}
			
		}

	}

}
//删除数据
void deleteData(List* pList, int value)
{
	node* p = NULL;
	p = pList->head;
	while (p!=NULL)
	{
		if (p->value == value)
		{
			break;//找到匹配的值,跳出循环
		}
		else
		{
			p = p->next;//指针向前递增
		}
	}
	//p存储了匹配值的指针
	if (p != NULL)
	{
		if (p != pList->head && p != pList->tail)//匹配在链表中间
		{
			p->per->next = p->next;//p->per->next 代表当前匹配元素的前一个元素 让 当前匹配元素的前指针 存储的对象的 后指针 指向 当前匹配元素的后指针 (链表连接跳过当前元素)
			p->next->per = p->per;//p->next->per 代表当前匹配元素的后一个元素 改变前 指向
			free(p);//释放
		}
		else if(p==pList->head)//匹配在链表头部
		{
			pList->head = p->next;//改变头节点的指向
			p->next->per = NULL;//p->next 代表当前匹配元素的下一个元素 
			free(p);
		}
		else if(p==pList->tail)//匹配在链表尾部
		{
			pList->tail = p->per; //改变尾节点指向 指向当前匹配元素的前指针
			p->per->next = NULL;//p->per 代表当前匹配元素的前一个元素
			free(p);
		}
	}
	
}

主函数测试调用:


#include"list.h"

void main()
{
	List list;
	init(&list);//初始化

	addOfHead(&list, 1);//添加元素
	addOfHead(&list, 2);
	addOfHead(&list, 3);
	addOfHead(&list, 4);
	addOfHead(&list, 5);
	showPositive(&list);//输出
	insertData(&list, 2, 33);//插入元素
	printf("\n\n");
	showPositive(&list);
	printf("\n\n");
	deleteData(&list, 3);//删除前,需要先判断是否有数据

	node* pNode1= findPositive(&list, 4);//查找元素
	if (pNode1 != NULL)
	{
		pNode1->value = 40;
	}

	node* pNode2=findReversed(&list, 40);//查找元素
	if (pNode2 != NULL)
	{
		pNode2->value = 44;
	}

	

	showReversed(&list);

	system("pause");
}

双链表结构图:

 

头部插入:

尾部插入:

删除匹配节点:

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值