数据结构之双端队列链式存储(C语言)

双链表的定义:

结点的内部

数据域用来存储数据

pre指针用来指向前面的结点

next指针用来指向后面的结点

typedef struct linkqueue{
	int date;//数据元素
	struct linkqueue *pre;
	struct linkqueue *next; 
	//int size;元素个数 
}node; 

全局变量:

定义一个中间结点用来标记表头,同时中间结点也用来存储数据,防止从左删到右边的时候,空的中间结点出现问题

定义左结点和右结点

//全局变量;
node *mid;//中间结点,标记中间位置类似链表头结点作用,实际上我们用不到 
//但是中间结点也存数据。避免从左删到右边时,空的中间结点出问题,画图举例 
node *left;
node *right;//左右两端 

初始化函数:

先将动态内存分配的首地址都赋给左指针和右指针(即左右指针都标记了此头结点)

之后让头结点的pre指针和next指针都指向NULL

//初始化
void initqueue()
{
left=right=(node* )malloc(sizeof(node));
	left->pre=left->next=NULL;

 } 

左插函数:

先创建一个结点s并且动态内存分配一片空间

将数据写入s的数据域

s的pre指针指向NULL

s的next指针指向左指针所标记的结点

之后左指针标记s结点

void insert_left(int k)
{
	node *s=(node* )malloc(sizeof(node));
	s->date =k;
	//插入 
	s->pre =NULL;
	s->next =left;
	left->pre =s;
	
	left=s;
 } 

左删函数:

先判断左指针是否为空或者左直至是否和右指针地址相同(此时表示左边没有剩余元素)

如果空则之间退出函数

非空则创建结点s

再将左指针指向的结点赋给结点s

左结点指向s的next指针所指向的结点

之后s的next指针和pre指针都与链表断开

之后free掉s结点

void de_left()
 {
 	if(left==NULL||left==right)
	 {
	 	printf("空表\n");//空,报错处理
		 return ; 
	  } 
 	node *s;
 	s=left;
 	left=left->next;
 	s->next=NULL;
 	left->pre=NULL;
 	//int x=s->data;
 	free(s);
  } 

右插函数:

先创建一个结点s并且动态内存分配一块空间

让s的next指针指向NULL

将k写入right指针所指向的结点的数据域中

再让right指针所指向的结点的next指针指向s结点

将s的pre指针指向right指针所指向的结点

最后让right指针指向s结点(右插是先写入数据再指针右移)

void insert_ri(int k)
{//right指向队尾的下一个元素 
	node *s=(node* )malloc(sizeof(node));
	s->next =NULL;
	right->date =k;
	right->next =s;
	s->pre =right;
	
	right=s;
	 
 }

右删函数:

先判断right指针所指向的pre指针指向是否为NULL(为空表示此结点前面没有任何结点)

则直接退出函数

之后创建结点s

将右指针所指向结点地址赋给s(此时s结点即为此被指向的结点)

再让right指针所指向的结点的pre指针所指向的结点的地址赋给right指针

(此时right指针向前移动一格)

void de_ri()
{//注意删的是right->pre ,right->pre才是真正的最后一个
//实际操作时只需要把right删掉,即可,画图讲解 
	if(right->pre==NULL)
	 {
	 	printf("空表\n");//空,报错处理
		 return ; 
	  }
	node *s;
	s=right;
	right=right->pre; 
	//int x=right->date;
	s->pre=NULL;
	right->next=NULL; 
	free(s);
	   
  } 

双端队列打印函数:

创建结点s

将左指针的地址赋给s

此时s结点即为左指针所标记的结点

之后按照链表打印的方法来打印此链表

(循环判断s的地址是否和right指针所标记的空结点地址是否相同或者s结点地址是否为空)

  void printff()
  {
  	node *s;
  	s=left;
  	while(s!=right&&s!=NULL)
  	{
  		printf("%d ",s->date); 
  		s=s->next; 
	  }
	  printf("\n");
  }

总代码:

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

#define msize 10

typedef struct linkqueue{
	int date;//数据元素
	struct linkqueue *pre;
	struct linkqueue *next; 
	//int size;元素个数 
}node; 
//全局变量;
node *mid;//中间结点,标记中间位置类似链表头结点作用,实际上我们用不到 
//但是中间结点也存数据。避免从左删到右边时,空的中间结点出问题,画图举例 
node *left;
node *right;//左右两端 
//初始化
void initqueue()
{
left=right=(node* )malloc(sizeof(node));
	left->pre=left->next=NULL;

 } 

//左边
void insert_left(int k)
{
	node *s=(node* )malloc(sizeof(node));
	s->date =k;
	//插入 
	s->pre =NULL;
	s->next =left;
	left->pre =s;
	
	left=s;
 } 
void de_left()
 {
 	if(left==NULL||left==right)
	 {
	 	printf("空表\n");//空,报错处理
		 return ; 
	  } 
 	node *s;
 	s=left;
 	left=left->next;
 	s->next=NULL;
 	left->pre=NULL;
 	//int x=s->data;
 	free(s);
 	
  } 
//右边 
void insert_ri(int k)
{//right指向队尾的下一个元素 
	node *s=(node* )malloc(sizeof(node));
	s->next =NULL;
	right->date =k;
	right->next =s;
	s->pre =right;
	
	right=s;
	 
 }
void de_ri()
{//注意删的是right->pre ,right->pre才是真正的最后一个
//实际操作时只需要把right删掉,即可,画图讲解 
	if(right->pre==NULL)
	 {
	 	printf("空表\n");//空,报错处理
		 return ; 
	  }
	node *s;
	s=right;
	right=right->pre; 
	//int x=right->date;
	s->pre=NULL;
	right->next=NULL; 
	free(s);
	   
  } 
  void printff()
  {
  	node *s;
  	s=left;
  	while(s!=right&&s!=NULL)
  	{
  		printf("%d ",s->date); 
  		s=s->next; 
	  }
	  printf("\n");
  }
  int main()
  {
  	initqueue();
  	insert_left(1);
  	insert_left(2);
  	insert_left(3);
  	insert_ri(4);
  	insert_ri(5);
  	printff();
  	
  	
  	//de_ri();
  	//printff();
  	insert_ri(6);
  	de_left();
  	de_left();
  	de_left();
  	de_ri();
  	printff();
  
  	
   } 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值