栈和队列--c/c++

栈和队列

文章目录

一、栈和队列的定义和特点
二、栈的表示和操作的实现
三、栈与递归
四、队列的表示和操作的实现

一、栈和队列的定义和特点

1.1

栈和队列是限定插入和删除只能在表的“端点”进行的线性表。
栈—后进先出–LIFO
队列–先进先出–FIFO

1.11

:是一个特殊的线性表,是限定仅在一端(表尾)进行插入删除的线性表。

栈的应运
1、数制转化 2、表达式求值
3、括号匹配的检验 4、八皇后问题
5、 行编辑程序 6、 函数调用
7、迷宫 8、递归调运的实现


表尾—栈顶–top
表头—栈底—base
入栈—插入元素到栈顶的操作----PUSH
出栈—从栈顶删除最后一个元素------POP
1,12
逻辑结构:同线性结构相同,仍为一对一关系
1.13
存储结构:用顺序栈或链栈存储均可;
1.14
运算规则:只能在栈顶运算,LIFO
(一般线性表—运算规则—随机存取)

1.2 对列

1.21
定义:只能在表的一端插入运,在另一端进行删除操作的线性表。
1.22
逻辑结构:同线性结构相同,仍为一对一关系
1.23
存储结构
顺序对或链队
1.24
只能在队首和队尾运算,先进先出(FIFO)


队列应运
1、脱机打印输出
2、所用户系统中。多个用户排成对。每个优先级一个队列
3、网络电文传输,按时间先后顺
4.舞伴问题

二、栈的表示和操作的实现

2.1 顺序栈的表示和实现

空栈:base == top是栈空的标志
栈满:top-base==stacksize(栈可以使用的最大容量)
上溢(overflow):栈已满就,又要压入新元素;
下溢(undetflow):栈已经空,还要弹出新元素;
顺序栈的表示

#define maxsize 100
typedef  struct{
       selemtype *base;//栈底指针
       selemtype *top;//栈顶指针
       int stacksize;//栈的可用最大容量
       }sqstack;

顺序栈的初始化

status initstack(sqstack  &s)//构建一个空栈
{
s.base=new selemtype[maxsize];
//s.base=(selemtype*)malloc(maxsize*sizeof(selemtype));
if(!s.base)exit(overflow);//存储分配失败
s.top=s.base;
s.stacksize=maxsize;
return ok;
}

顺序栈判断栈是否为空

status stackempty(sqstack s)
{//若栈为空,返回1;否则返回0;
if(s.top==s.base)
return 1;
else
return 0;
}

求顺序栈的长度

int stacklength(sqstack s)
{
return s.top-s.base;
}

清空顺序栈

status clearstack(sqstack s)
{
if(s.base)s.top=s.base;
return 1;
}

销毁顺序栈

status destroystack(sqstack &s)
{
if(s.base)
{
delete s.base;
s.stacksize=0;
s.base=s.top=NULL;
}
return ok;
}

顺序栈的入栈
//判断是否栈满
//元素e压入栈
//栈指针加1

 status push(sqstack &s,selemtype e)
 {
 if(s.top-s.base==s.stacksize)//栈满
 return 0;
 *s.top++=e;//*s.top=e;s.top++;
 return 1;
 }

顺序栈的出栈

status pop(sqstack &s,selemtype &e)
{
if(s.top==s.base)//等价于 if(stackempty(s));
return 0;
e=*--s.top;//--s.top;e=*s.top;
return ok;

}

/

2.2链栈的表示和实现

链栈是运算受限的单链表,只能在链表头部进行操作

typedef struct stacknode{
  selemtype data;
  struct stacknode *next;
}stacknode,*linkstack;
linkstack s;

链栈的初始化

void initstack(linkstack &s)
{
//构建一个空栈,栈顶指针置为空;
s=NULL;
return ok;
}

判断链栈是否为空

status stackempty(linkstack s)
{
if(s==NULL)return 1;
else return 0;
}

链栈的入栈

status push(linkstack &s,selemtype e)
{
p=new stacknode;
p->data=e;//将新节点数据域置为e;
p->next=s;//将新节点插入栈顶
s=p;、、修改栈顶指针;
return ok;
}

链栈的出栈

status pop (linkstack &s,selemtype &e)
{
if(s==NULL)return 0;
e=s->data;
p=s;
s=s->next;
delete p;
return ok;
}

取栈顶元素

selemtype gettop(linkstack s)
{
if(s!=NULL)
return s->data;
}

三、栈与递归

递归
优点:结构清晰,程序易读;
缺点:每次调试要生成工作记录,保存状态信息。入栈;返回时要出栈,恢复状态信息。时间开销大。
递归->非递归
方法一:尾递归,单向递归->循环结构;
方法二:自用栈模拟系统的运行时栈
尾递归->循环结构

long fact(long n)
{
if(n==0)return 1;
else return n*fact(n-1);
}

等价于

long fact (long n)
{
t=1;
for(i=1;i<=n;i++)
t=t*i;
return t;
}

单项递归->循环结构

long fib(long n)
{
if(n==1||n==2)return 1;
else return fib(n-1)+fib(n-2);
}

等价于

long fib (long n)
{
t1=1;t2=1;
for(int i=3;i<=n;i++)
{
t3=t1+t2;
t1=t2;t2=t3;
}
return t3;
}

四、队列的表示和操作的实现

1.定义:只能在表的一端插入运,在另一端进行删除操作的线性表。
2.逻辑结构:同线性结构相同,仍为一对一关系
3.存储结构
顺序对或链队
4、实现方式:入队和出队操作。
入队:插入元素
出队:删除元素
4.1队列的顺序表示–用一维数组base[maxqsize]

入队
base[raer]=x;
rear++;
出队
x=base[front];front++;
这样做容易出现假溢出。怎么解决?这就需要引入循环队列

循环队列

#define maxqsize 100;//最大化队列长度
typedef struct{
qelemtype *base;//初始化的动态分配内存
int front;
int rear;
}sque;

循环队列–队列初始化

status initque(sque &q)
{
q.base=new qelemtype[maxqsize]//分配数组空间c++
//q.base=(qelemtype*)malloc(maxqsize*sizeof(qelemtype));
if(!q.base)exit(overflow);
q.front=q.rear=0;
return ok;
}

队列长度

int quelength(aque q)
{
return (q.rear=q.front +maxqsize)%maxqsize};

入队

status enque(sqque &q,qelemtype e)
{
if((q.rear+1)%maxqsize==q.front )
return error;
q.base[	q.rear]=e;
q.rear=(q.rear+1)%maxqsize;
return ok;
}

出队

status deque(sqque &q,qelemtype &e)
{
if(q.front==q.rear)return error;//对空
e=q.base[q.front];//保存对头元素
q.front=(q.front+1)%maxqsize;//对头指针+1
return ok;
} 

取队头元素

status gethead(sqque q)
{
if(q.front!=q.rear)//队列不为空
return q.base[q.front];//返回队头指针元素的值吗,队头指针不变;
}

链队

若无法估计所用队列的长度,则宜采用链队
链队列定义

#define maxqsize 100
typedef struct qnode{
qelemtype data;
struct qnode *next;
}qnode,*queneptr;
typedef strulct {
queneptr  front;
queneptr rear;
}linkque;

链队列初始化

status initque(linkqule &q )
{
q.front=q.rear=new qnode;//c++
//q.front=q.rear=(queneptr)malloc(sizeof(qnode));c
if(!q.front)exilt(overflow);
q.front->next=NULL;
return ok;
}

销毁队列

status destroyque(linkque &q)
{
while(q.front)
{
p=q.front->next;free(q.front);
q.front=p;
}
return ok;
}

将元素e入队

status enque(linkque &q,qelemtype e)
{
p=new qnode;
if(!p)exit(overflow);
p->data=e;p->next=NULL:
q.rear->next=p;
q.rear=p;
return ok;
}

链队出队

status deque(linkque &q,qelemtype &e)
{
if(q.front==q.rear)return ERROR;
p=q.front->next;
e=p->data;
q.front->next=p->next;
if(q.rear==p)
q.rear=q.front;
delete p;
return ok;
}e

求链队的队头的元素

status gethead(linkque q,qelemtype &e)
{
if(q.front==q.rear)return error;
e=q.front->next->data;
return ok;
}

代码的话在下一篇文章中;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值