双向链表【C语言】

写在前面的话:

  1. 编译器:DevC++
  2. 文本编辑器:Sublime Text3
  3. 本章内容:双向链表的使用

1.效果截图

 2.全部代码

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

struct node //节点
{
	int data; //数据域 也是可以有很多
	struct node *prev; //前指针
	struct node *next;//后指针
};

//初始化链表
struct node *init_list()
{
	struct node *head = malloc(sizeof(struct node));//申请空间 
	if (head != NULL)
	{
		head->prev = head; //指针指向自己
		head->next = head;
	}
	return head;
}

//创建新节点 和单链表就多了一个前指针而已
struct node *create_new_node(int m)
{
	struct node *newNode = malloc(sizeof(struct node));//申请空间 
	//申请空间成功 
	if (newNode != NULL)
	{
		newNode->prev = newNode; //指针指向自己
		newNode->next = newNode;
		newNode->data = m;//将参数m赋值给结构体中的data 
	}
	return newNode;
}

//尾插法,找到最后一个节点进行插入
void insert_node(struct node *head,struct node *newNode)
{
	struct node *p = head;
	while(p->next != head)//遍历到下一个节点是头节点,此时就是链表当中最后一个节点 
	{
		p = p->next;//一直遍历下一个节点 
	}
	newNode->next = p->next; //新指针next指向头
	newNode->prev = p;//新指针prev指向最后一个节点
	p->next->prev = newNode;//头指针的前指针指向新节点
	p->next = newNode;//最后一个节点的next指针指向新节点
}

//将链表打印出来 
void showlist(struct node *head)
{
	struct node *p = head->next;//定义一个指针指向首节点(第一个节点) 
	printf("[链表]");
	while(p != head)//当节点等于头节点,说明已经遍历完整个链表了,退出循环 
	{
		printf("%d ",p->data );//将节点的数据打印出来 
		p = p->next;//遍历下一个节点 
	}
	printf("\n");
}

//判断参数m是否存在于链表当中 
bool exist(struct node *head,int m)
{
	struct node *p = head->next;//定义一个指针指向首节点(第一个节点) 
	while(p != head)//当节点等于头节点,说明已经遍历完整个链表了,退出循环 
	{
		if (p->data == m)//如果在链表中,查询到参数m,执行以下语句 
		{
			printf("该节点已经存在\n");
			return true;//存在于链表当中,返回true 
		}
		p = p->next;//遍历下一个节点 
	}
	return false;//不存在于链表当中,返回false 
}

struct node * delete_node(struct node *head,int n)
{
	struct node *p = head->next;//定义一个指针指向首节点(第一个节点) 
	while(p != head)//当节点等于头节点,说明已经遍历完整个链表了,退出循环 
	{
		if (p->data == n) //p指向的是我想删除的节点
		{
			p->prev->next = p->next;//由p节点的前一个节点的next指针指向p节点的后一个节点 
			p->next->prev = p->prev;//由p节点的后一个节点的prev指针指向p节点的前一个节点 
			return p;
		}
		p = p->next;//遍历下一个节点 
	}
	printf("没找到该节点 无法删除\n");//当遍历完整个链表,没有找到参数m 

}

//头插法  来一个节点就插入到头的后面
void insert_head(struct node *head,struct node *newNode)
{
	newNode->next = head->next;
	newNode->prev = head;
	head->next->prev = newNode;
	head->next = newNode;
}

//尾插法 找到头节点即可,在头节点之前插入节点
void insert_last(struct node *head,struct node *newNode)
{
	//不需要找最后一个节点 ,最后一个节点是head->prev保存的
	newNode->next = head;//新节点的next指针指向头节点 
	newNode->prev = head->prev;//新节点的prev指针指向头节点的前一个节点 
	head->prev->next = newNode;//头节点的前一个节点的next指针指向新节点 
	head->prev = newNode;//头节点的prev指针指向新节点 
}

//奇偶排序 
void odd_even(struct node *head)
{
	struct node *p = head->prev;//指向最后一个节点 
	struct node *tmp = p->prev;//指向p节点的前一个节点 
	
	while(p!=head)//遍历整个链表 
	{
		tmp = p->prev;//每一次循环都遍历前一个节点 
		if (p->data%2 == 0)//如果该节点的数据是偶数,就执行以下语句 
		{
			/*
				思路: 
					1.判断该节点是否是偶数,若是偶数,进入第2步,否则跳过 
					1.删除该节点
					2.将其插入到末尾 
			*/
			p = delete_node(head,p->data);//删除该节点 
			insert_last(head,p);//再从尾部插入节点 
		}
		p = tmp;//将P指针指向tmp指向的节点 	
		
		if(p == head){//如果p指针指向了头节点
			break;//直接跳出循环 
		}	
	}
}

int main(int argc, char const *argv[])
{
	int i = 0;//循环变量 
	
	//初始化链表
	struct node *head=init_list(); 

	for (i = 1; i < 9; i++)
	{
		struct node *newNode = create_new_node(i);//创建节点 
		insert_node(head,newNode);//插入到链表当中 
	}
	showlist(head);//打印链表 
	odd_even(head);//经过奇偶排序 
	printf("\n奇偶排序:\n");
	showlist(head);//打印经过奇偶排序后的链表 
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Fy哥

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

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

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

打赏作者

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

抵扣说明:

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

余额充值