数据结构 第三章 栈和队列

第三章 栈和队列

 

 

栈(Stack)是限定只能在表的一端进行插入和删除操作的线性表。在表中,允许插入和删除的一端称作"栈顶(top)",不允许插入和删除的另一端称作"栈底(bottom)" 。

数据对象:D={ai|ai∈ElemSet, i=1,2,...,n, n≥0 }

数据关系:R1={ <ai-1, ai>|ai-1,ai∈D, i=2,...,n } 约定an端为栈顶,a1 端为栈底。

栈有两种存储表示,其顺序存储结构简称为顺序栈。

一、顺序栈类型的定义

// 结构定义:

typedefstruct {

ElemType*base; // 存储空间基址

inttop;        // 栈顶指针

intstacksize;   // 允许的最大存储空间以元素为单位

}Stack;

和顺序表类似,对顺序栈也需要事先为它分配一个可以容纳最多元素的存储空间,base 为这个存储空间的基地址,也即一维数组的地址。

从名称来讲,"栈顶指针"意为指示栈顶元素在栈中的位置,但它的值实际是栈中元素的个数,和顺序表中的 length 值的意义相同。

// 基本操作接口(函数声明):
 void InitStack (Stack &S,int maxsize);
 // 构造一个最大存储容量为 maxsize 的空栈S。
void DestroyStack (Stack &S);
 // 销毁栈S,S 不再存在。
void ClearStack (Stack &S);
 // 将 S 置为空栈。
bool StackEmpty (Stack S);
 // 若栈 S 为空栈,则返回 TRUE,否则返回 FALSE。

intStackLength (Stack S);
 // 返回S的元素个数,即栈的长度。
bool GetTop (Stack S, ElemType &e);
 // 若栈不空,则用 e 返回S的栈顶元素,并返回TRUE;否则返回FALSE。

boolPush (Stack &S, ElemType e);
 // 若栈的存储空间不满,则插入元素 e 为新的栈顶元素,并返回 TRUE;
 // 否则返回FALSE。
bool Pop (Stack &S, ElemType &e);
 // 若栈不空,则删除S的栈顶元素,用e返回其值,并返回TRUE;否则返回FALSE。

voidStackTraverse(Stack S, void (*visit(ElemType ))
 // 依次对S的每个元素调用函数visit( ),一旦 visit( )失败,则操作失败。

在此只给出其中4个函数的定义。
  对顺序栈来说,空栈的初始化和顺序表的初始化完全相同。这不奇怪,因为它们的结构是一样的。也就是说,并非对栈而言取不到除栈顶之外的元素,而是对栈类型来说,不允许这种操作。

void InitStack (Stack &S,intmaxsize)
 {
   // 构造一个最大存储容量为 maxsize 的空栈 S
if (maxsize == 0)
   maxsize = MAXLISTSIZE;
  S.base = new SElemType[maxsize];
  if (!S.base) exit(1);    // 存储分配失败
S.stacksize = maxsize;
  S.top = 0;          // 空栈中元素个数为0
 }

 

在此定义中,栈顶指针的值恰为当前栈中元素个数,栈顶指针的初值为0和栈中元素个数为0是同一个含义。

bool GetTop (StackS, ElemType &e)
{
 // 若栈不空,则用 e 返回S的栈顶元素,并返回TRUE;否则返回FALSE
if (S.top == 0) return FALSE;
  e = *(S.base + S.top-1);   //返回非空栈中栈顶元素
return TRUE;
 }

 *(S.base+ S.top-1)是S.base[S.top-1] 的另一种写法,其实质相同。

bool Push (Stack&S, ElemType e)
{
 // 若栈的存储空间不满,则插入元素 e 为新的栈顶元素,
 // 并返回 TRUE;否则返回 FALSE

  if (S.top == S.stacksize)  //栈已满,无法进行插入
   return FALSE;
  *(S.base + S.top) = e;    // 插入新的元素
  ++S.top;          // 栈顶指针后移
return TRUE;
 }

bool Pop (Stack&S, ElemType &e)
{
 // 若栈不空,则删除S的栈顶元素,用 e 返回其值,
 // 并返回 TRUE;否则返回 FALSE

if (S.top == 0) return FALSE;
  e = *(S.base + S.top-1);   //返回非空栈中栈顶元素
  --S.top;          // 栈顶指针前移
return TRUE;
 }

1. 队列的基本概念

(1)队列是一种特殊的、只能在表的两端进行插入或删除操作的线性表。允许插入元素的一端称为队尾,允许删除元素的一端称为队首。

(2)队列的逻辑结构和线性表相同,其最大特点是“先进先出”。

(3)队列的存储结构有顺序队列和链队列之分,要求掌握队列的C语言描述方法。

(4)重点掌握在顺序队列和链队列上实现:进队、出队、读队头元素、显示队列元素、判队空和判队满等基本操作。

(5)熟悉队列在计算机软件设计中的典型应用,能灵活应用队列的基本原理解决一些实际应用问题。

2. 顺序队列(1)顺序队列用内存中一组连续的存储单元顺序存放队列中各元素,一般用一维数组作为队列的顺序存储空间。除了队列的数据以外,一般还设有队首和队尾两个指针。typedef struct{ datatype Q[MAXLEN]; int front=–1, rear=–1; // 定义队头、队尾指针,并置队列为空}Queue;

(2)顺序队列缺点是存在“假溢出”现象。

3.循环队列(1)为了解决顺序队列中的“假溢出”现象,把数组想象成一个首尾相连的环,即队首的元素Q[0]与队尾的元素Q[MAXLEN–1]连接起来,存储在其中的队列称为循环队列。

(2)一般规定:当front= =rear,表示循环队列为空;当front= =(rear+1)% MAXLEN,表示循环队列为满

(3)在定义结构体时,附设一个存储循环队列中元素个数的变量n,当n= =0时表示队空;当n= = MAXLEN时为队满。循环队列的结构体类型定义:typedef struct{ datatype data[MAXLEN]; int front,rear; int n; // 用以记录循环队列中元素的个数}csequeue; // 循环队列变量名

(4)入队操作时:p->rear= (p->rear+1) % MAXLEN;出队操作时:p->front= (p->front+1) % MAXLEN;

4. 链队列

(1)队列的链式存储结构称为链队列(或链队)。链首结点为队头,链尾结点为队尾。

(2)链队列的描述: typedef struct queuenode{ datatype data;  struct queuenode *next;}queuenode;    // 链队结点的类型datatypetypedef struct{ queuenode *front,*rear;}linkqueue; // 将头指针、尾指针封装在一起的链队如下图

(3)若队头指针为Q->front,队尾指针为Q->rear,则队头元素的引用为Q->front->data,队尾元素的引用为Q->rear->data。

(4)初始时置Q->front=Q->rear=NULL。

(5)入队操作,与链表中链尾插入操作一样;出队操作,与链表中链首删除操作一样。

(6)队空标志为Q->front==NULL;对于链队列而言,一般不会出现队满。

栈的应用举例

数制转换
括弧匹配检验
迷宫求解问题

表达式求值问题

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值