数据结构之双链表(C语言代码)

双向链表

一、什么是双向链表

双向链表又称双链表,是链表的一种,和单链表一样,也是把多个结构体节点用结构体指针连接起来,只不过单链表只有一个指向下一个节点的结构体指针,而双链表有两个结构体指针分别指向上一个节点和下一个节点。

二、双向链表的特点

1、双链表和单链表一样,没有固定的长度,可以自由增加节点
2、双链表有两个指针域,一个用于指向前一个节点,另一个用于指向下一个节点
3、由于有指向前一个节点的指针域,双链表可以很好的支持逆序输出

三、双向链表和单向链表的区别

单链表只有一个指针域,用于指向下一个节点的首地址,而双链表有两个指针域,可以分别指向前一个节点和下一个节点,链表的遍历更加方便

四、双链表的结构示意图在这里插入图片描述

五、双链表的设计与功能实现

1、创建双链表节点
2、链接双链表节点
3、双链表的打印输出
4、双链表节点的删除
5、双链表的销毁
6、双链表的连接

定义一个结构体,存放数据和指针
struct Node
{
	int x;
	int y;
	Node* prev;   //定义一个结构体指针, 保存该节点上一个节点在内存中的地址
	Node* next;   //定义一个结构体指针, 保存该节点下一个节点在内存中的地址
};
创建链表结构体
struct Linklist  
{
	Node* head; //保存头节点的地址
	Node* tail; //保存尾接点地址
	int size;  //保存节点个数
};
创建链表中存放数据的节点
Node* createNode(int x, int y)
{
	Node*temp= (Node*)malloc(sizeof(Node));//申请一个节点的内存 , 并且指向这段内存
	temp->x = x;
	temp->y = y;
	temp->next = NULL;
	temp->prev = NULL;
	return temp;
}
定义一个函数,传入两个节点
void node_link(Node* n1, Node* n2)
{
	n1->next = n2;
	n2->prev = n1;
}
初始化双链表
void Linklist_init(Linklist*list)
{
	list->head = NULL; //头尾指针置空,大小为0
	list->tail = NULL;
	list->size = 0;
}
头插法
void push_head(Linklist* list, int x, int y)
{
	if (list->head == NULL)
	{
		//创建节点,因为是第一个节点,所以头节点等于尾接点
		list->head = createNode(x,y);
		list->tail = list->head;
		list->size = 1; //有一个节点
	}
	else
	{
		Node* temp = createNode(x, y); //定义临时指针变量接收新节点的地址
		node_link(temp, list->head); //头插
		list->head = temp;
		list->size++;
	}
}
尾插法
void push_tail(Linklist* list, int x, int y)
{
	if (list->head == NULL)
	{
		list->head = createNode(x, y);
		list->tail = list->head;
		list->size = 1;
	}
	else
	{
		Node* temp = createNode(x, y);
		node_link(list->tail, temp);
		list->tail = temp;
		list->size++;
	}
}
顺序输出
void printhead_list(Linklist*p)
{
	if (p->head == NULL)
	{
		printf("该双链表为空!");
		return;
	}
	else
	{
		Node* temp = p->head;
		printf("头输出为:\n");
		//定义一个临时指针指向链表头节点
		while (temp!= NULL)
		{
			printf("x=%d y=%d\n", temp->x, temp->y);
			temp = temp->next;
		}
		
	}
}
逆序输出
void printend_list(Linklist* p)
{
	if (p->head == NULL)
	{
		printf("该双链表为空!");
		return;
	}
	else
	{
		printf("尾输出为:\n");
		Node* temp = p->tail;
		while (temp != NULL)
		{
			printf("x=%d y=%d\n", temp->x, temp->y);
			temp = temp->prev;
		}
	}
}
删除符合条件的节点
void deleteNode(Linklist*p, int x)
{
	assert(list);//断言 , 判断list是否为空 ,如果为空, 程序结束
	if (p== NULL)
		return;
	Node* temp = p->head;
	while (p != NULL)
	{
		if (temp->x == x)
		{
			Node* tt = temp;
			node_link(tt->prev, tt->next);
			temp = temp->next;
			free(tt);
		}
		else
		temp = temp->next;
	}
}
删除指定节点
void deletelink(Linklist* p)
{
	if (p != NULL)
	{
		Node* temp = p->head;
		while (temp != NULL)
		{
			Node* tt = temp;
			temp = temp->next;
			free(tt);
		}
		Linklist_init(p);
	 }
}
删除头节点
void deletelisthead(Linklist* list, Node* node)
{
	assert(list->head);//判断链表是否为空
	if (node == list->head)//如果删除的是头节点
	{
		Node* temp = list->head;
		list->head = list->head->next;
		if (list->head == NULL)
			list->tail = NULL;
		else
			list->head->prev = NULL;
		free(temp);
	}
	else if (node == list->tail)
	{
		Node* temp = list->tail;
		list->tail = list->tail->prev;
		if (list->tail == NULL)
		{
			list->head == NULL;
		}
		else
			list->tail->next = NULL;
		free(temp);
	}
	else
	{
		node_link(node->prev, node->next);
		free(node);
	}
	list->size--;
}
销毁链表
void destory(Linklist* list)
{
	for (Node* temp = list->head; temp != NULL;)
	{
		Node* tt = temp;
		temp = temp->next;
		free(tt);
	}
	Linklist_init(list);
}
链表节点数
void Looklistsize(Linklist* list)
{
	printf("双链表的大小为%d\n", list->size);
}
连接两个双链表
Linklist* linklists(Linklist* list1, Linklist* list2)
{
	Linklist *list3= (Linklist*)malloc(sizeof(Linklist));
	Linklist_init(list3);
	Node* temp = list1->tail;
	Node* tt = list2->head;
	node_link(temp, tt);
	list3->head = list1->head;
	list3->tail = list2->tail;
	list3->size = list1->size + list2->size;
	return list3;
}
测试
int main()
{

	Linklist* list1 = (Linklist*)malloc(sizeof(Linklist));
	Linklist_init(list1);
	Linklist* list2 = (Linklist*)malloc(sizeof(Linklist));
	Linklist_init(list2);
	Linklist* list3 = (Linklist*)malloc(sizeof(Linklist));
	Linklist_init(list3);
	for (int i = 0; i < 10; i++)
	{
		push_head(list1, i * 1, i * 1);
		//push_head(list2, i * 2, i * 2);

	}
	for (int i = 0; i < 10; i++)
	{
		//push_head(list1, i * 1, i * 1);
		push_head(list2, i * 2, i * 2);

	}
	list3 = linklists(list1, list2);
	//deleteNode(list, 2);
	//printend_list(list);
	//printhead_list(list);
	//destory(list);
	//for (Node*temp=list->head;temp!=NULL;temp=temp->next)
	//{
	//	Node* tt = temp;
	//	if (temp->x == 3 || temp->y == 5)
	//	{
	//		deletelisthead(list,tt);
	//	}
	//}
	printf("list1和list2双链表连接成功后的数据为:\n");
	printend_list(list3);
	Looklistsize(list3);

	system("pause");
	return 0;
}
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值