6栈与队列
栈
只允许在同一个端点处进行插入、删除的表结构称为栈(stack)
属性:
栈顶(top)指针
栈底(bottom)
进栈(push)
退栈(pop)
特点:
后进先出。或LIFO表 (last in first out)
顺序栈的进栈、出栈算法:
#define EMPTY -1 //栈空指针值
#define SUCC 1 //操作成功标记
#define FAIL 0 //操作失败标记
const int m=1000; //栈空间大小
Typedef int element_type; //元素类型
void push(element_type s[ ],int &top,element_type x) //进栈函数
{
if(top==m-1)
return FAIL;
[++top]=x;
return SUCC;
}
void push(element_type s[ ],int &top,element_type &x) //退栈函数
{
if(top==EMPTY )
return FAIL;
x=s[top- -];
return SUCC;
}
上面是静态数值,空间有限,下面是动态数组。。
使用动态数组的进退栈算法
整体变量定义:
#define SUCC 1 //操作成功标记
#define FAIL 0 //操作失败标记
unsigned m=500; //预定的栈空间大小
unsigned delta=100; //追加增量
typedef int element_type ; //元素类型
typedef element_type *eptr ; //指针类型
eptr p; //指向栈空间
开始时预分配栈空间
top=p=(eptr)malloc(m*sizeof(element_type));
进栈函数
void dpush(eptr &p,eptr &top,element_type x)
//p是当前栈空间起始指针,top是栈顶指针
//x是要求进栈的元素
{
if(top==p+m) //溢出
{
m+=delta; //追加增量
p=(eptr)realloc(p,m*sizeof(element_type)); //分配更大的空间
top=p+m-delta; //重定栈顶指针
}
*top=x; //x进栈
++top;
}
退栈函数
int dpop(eptr &p, eptr &top,element_type &x)
//p是当前栈空间起始指针,top是栈顶指针
//x接收退栈元素
//返回值 SUCC:退栈成功;FAIL:退栈不成功
{
if(top==p)
return FAIL; //栈空
top--;
x=*top; //x退栈
return SUCC ;
}
上讲介绍过链表,栈、队列也可以由一个个结点组成。。。。。。。。
链式栈的进栈、退栈算法
进栈函数
int push(ptr &top,element_type x)
{
ptr p;
p=new snode; //申请结点
if(p==NULL)return FAIL; //申请失败
p->data=x; //x进栈
p->next=top;
top=p;
return SUCC; //进栈成功
}
退栈函数
int pop(ptr &top,element_type &x)
{
ptr p;
if(top==NULL)return FAIL;//退栈不成功.
x=top->data;
p=top;
top=top->next;
free(p);
return SUCC; //退栈成功
}
队列
只允许在一端进行插入,在另一端进行删除的表结构称为队。
属性:
插入端,队尾(rear);删除端,队头(front)
first和last:分别指向队头元素和队尾元素
特点:
先进先出,或FIFO表
队列的进队、出队算法也栈类似,可以参考栈的静态、动态方法。下面主要讲讲循环队列和链式队列。
循环队列
特点:重复使用已退队元素所占存储单元!
注意:循环队列一定要判断队空或队满的情况。
队满情况:
1. 情况1: 在程序执行期间,如果要求进队的元素总量不超过数组长度m,就不会出现队满情况
2. 情况2: 在程序执行期间,需要进队处理的元素 总量多于m个,但任何时刻,队中的元素数目 始终小于m,仍可使用长度为m的数组存储(不会发生队满)
判断方法:
1.开始时,队空,指针first=last=0
2.若一段时间内,只进不出,last赶上first,满
3.若一段时间内,只出不进, first赶上last,空
4.当first等于last时,无所适从
循环队列的进队、出队算法
(1)进队函数
int addq(element_type q[ ], int first, int &last,element_type x )
{
if((last+1)%m==first)
return 0; //队满
q[last]=x;
last=(last+1)%m;.
return 1; //进队成功
}
(2)出队函数
int delq(element_type q[ ], int &first, int last,element_type &x )
{
if(first==last)
return 0;
x=q[first];
first=(first+1)%m;
return 1;
}
链式队列
链式队采用单向加头链表结构,first为首指针,last为尾指针。
进队:将新结点插在表尾处,last移向新结点。
出队:将队头元素所占结点作为新的头结点(头结点不固定),释放原来的头结点first和last,同时指向头结点作为队空的判断条件。
链式队的进出队算法
(1)进队函数
int saddq(ptr &last,element_type x)
{
ptr p;
p=(ptr)malloc(sizeof(snode));
if(p==NULL)
return FAIL;
p->data=x;
last->next=p;
last=p;
return SUCC; //进队成功
}
(2)出队函数
int sdelq(ptr &first,ptr last ,element_type &x)
{
ptr p;
if(first==last)
return FAIL; //队空
p=first;
first=p->next;
x=first->data; //x出队
free(p);
return SUCC; //出队成功
}
普通栈的源代码:
// Stack.cpp : 定义控制台应用程序的入口点。
//
---------------------------顺序栈
#include "stdafx.h"
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#define MAXSIZE 5
bool isPrint()
{
char ch=getch();
if(ch=='y'||ch=='Y')
return true;
else
return false;
};
int arr[MAXSIZE]={0};
int top=-1;
//进栈
void Push()
{
printf("请输入一个数据:");
int data;
scanf("%d",&data);
arr[++top]=data;
printf("剩余栈中空间%d\n",(MAXSIZE-top)-1);
if(top<(MAXSIZE-1))
{
printf("是否继续添加元素(Y/N)\n");
if(isPrint())
Push();
}
else
{
printf("栈已满\n");
};
};
//退栈
void Pop()
{
int x=0;
x=arr[top--];
printf("所退的元素是:%d\n",x);
printf("剩余栈中空间%d\n",(MAXSIZE-top)-1);
if(top>-1)
{
printf("是否继续删除元素(Y/N)\n");
if(isPrint())
Pop();
}
else
{
printf("栈已空\n");
};
};
int _tmain(int argc, _TCHAR* argv[])
{
Push();
Pop();
getchar();
return 0;
}
改进后
-----------------------------------------------------------------------------------
// Stack.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#define MAXSIZE 5
int arr[MAXSIZE]={0};
int top=-1;
void Pop();
int isPrint()
{
printf("1.进栈;2.出栈\n");
int k;
scanf("%d",&k);
if(k==1)
return 1;
else if(k==2)
return 2;
else
{
printf("输入错误!\n");
isPrint();
};
};
//进栈
void Push()
{
printf("请输入一个数据:");
int data;
scanf("%d",&data);
arr[++top]=data;
printf("剩余栈中空间%d\n",(MAXSIZE-top)-1);
if(top<(MAXSIZE-1))
{
int k=isPrint();
if(k==1)
Push();
else
Pop();
}
else
{
printf("栈已满\n");
Pop();
};
};
//退栈
void Pop()
{
int x=0;
x=arr[top--];
printf("所退的元素是:%d\n",x);
printf("剩余栈中空间%d\n",(MAXSIZE-top)-1);
if(top>=0)
{
int k=isPrint();
if(k==1)
Push();
else
Pop();
}
else
{
printf("栈已空\n");
};
};
int _tmain(int argc, _TCHAR* argv[])
{
Push();
getch();
return 0;
}
-----------------------------------------链式栈
// 813.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
void isPrint();
typedef struct Node
{
int data;
Node * next;
Node * prew;
};
Node * head=NULL;
Node * top=NULL;
//创建节点
Node * Create()
{
printf("请输入数据:");
int num;
scanf("%d",&num);
Node * pn=(Node *)malloc(sizeof(Node));
pn->data=num;
pn->next=NULL;
pn->prew=NULL;
return pn;
};
//插入节点
void Push()
{
Node * p=Create();
if(head==NULL)
{
head=p;
top=p;
head->next=NULL;
top->next=NULL;
}
else
{
top->next=p;
p->prew=top;
top=p;
top->next=NULL;
};
isPrint();
};
void Pop()
{
Node * p=NULL;
if(top==head&&head->next==NULL) //只有一个节点
{
free(head);
head=NULL;
}
else if(top->next==NULL)
{
p=top;
top=top->prew;
top->next=NULL;
free(p);
}
else
{
printf("栈中不存在数据");
};
isPrint();
};
void Select()
{
Node * ps=NULL;
ps=head;
while(ps!=NULL)
{
printf("%d\t",ps->data);
ps=ps->next;
};
if(head==NULL)
{
printf("栈中无数据");
isPrint();
}
isPrint();
};
void isPrint()
{
printf("\n");
printf("1.进栈;2.出栈;3.查看\n");
int k;
scanf("%d",&k);
if(k==1)
Push();
else if(k==2)
Pop();
else if(k==3)
Select();
else
{
printf("输入错误!\n");
isPrint();
};
};
int _tmain(int argc, _TCHAR* argv[])
{
Push();
system("pause");
return 0;
}
普通队列的源代码:
// queue.cpp : 定义控制台应用程序的入口点。
//
--------------------------------------------- 顺序队
#include "stdafx.h"
#include<stdio.h>
#define MAXSIZE 5
int rear=0;
int tail=0;
int arr[MAXSIZE]={0};
void isPrint();
//进队
void Push()
{
int num;
if(tail<MAXSIZE)
{
printf("请输入一个数据:");
scanf("%d",&num);
arr[tail]=num;
tail++;
printf("剩余队空间%d",MAXSIZE-tail);
};
if(tail>=MAXSIZE)
{
printf("\n队已满");
};
isPrint();
};
//出队
void Pop()
{
if(rear!=tail)
{
printf("%d\t",arr[rear]);
rear++;
};
if(rear==tail)
printf("\n队已空");
isPrint();
};
void isPrint()
{
printf("\n");
printf("1.进队;2.出队\n");
int k;
scanf("%d",&k);
if(k==1)
Push();
else if(k==2)
Pop();
else
{
printf("输入错误!\n");
isPrint();
};
};
int _tmain(int argc, _TCHAR* argv[])
{
Push();
getchar();
return 0;
}
---------------------------------------------------链式队
void isPrint();
typedef struct Node
{
int data;
Node * next;
Node * prew;
}Node;
Node * head=NULL;
Node * end=NULL;
//创建节点
Node * Create()
{
printf("请输入数据:");
int num;
scanf("%d",&num);
Node * pn=(Node *)malloc(sizeof(Node));
pn->data=num;
pn->next=NULL;
pn->prew=NULL;
return pn;
};
//插入节点
void Push()
{
Node * p=Create();
if(head==NULL)
{
head=p;
end=p;
head->next=NULL;
end->next=NULL;
}
else
{
p->next=head;
head->prew=p;
head=p;
};
isPrint();
};
void Pop()
{
Node * p=NULL;
if(end==head&&head->next==NULL) //只有一个节点
{
free(head);
head=NULL;
}
else if(end->next==NULL)
{
p=end;
end=end->prew;
end->next=NULL;
free(p);
}
else
{
printf("队中不存在数据");
};
isPrint();
};
void Select()
{
Node * ps=NULL;
ps=head;
while(ps!=NULL)
{
printf("%d\t",ps->data);
ps=ps->next;
};
if(head==NULL)
{
printf("队中无数据");
isPrint();
}
isPrint();
};
void isPrint()
{
printf("\n");
printf("1.进队;2.出队;3.查看\n");
int k;
scanf("%d",&k);
if(k==1)
Push();
else if(k==2)
Pop();
else if(k==3)
Select();
else
{
printf("输入错误!\n");
isPrint();
};
};
int _tmain(int argc, _TCHAR* argv[])
{
Push();
getchar();
return 0;
}