双链表的定义:
结点的内部
数据域用来存储数据
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();
}