栈的顺序实现

注意:每一个代码请对照教材相应的图,这样方便理解

顺序栈定义

const int maxsize=6;

typedef struct seqstack

{

  DataType data[maxsize];

  int top;

}SeqStk;

基本运算

1 初始化

int InitStack(SeqStk *stk)

{

  stk->top=0;

  return 1;

}

2 判栈空

int EmptyStack(SeqStk *stk)

//若栈为空,则返回值1,否则返回值0

{

  if (stk->top==0)

    return 1;

  else return 0;

}

3 进栈

int Push(SeqStk *stk,DataType x)

{//若栈未满,元素x进栈stk中,否则提示出错信息

  if (stk->top == maxsize-1)

    {

      error("栈已满");

      return 0;

    }

  else 

    {

      stk->top++;

      stk->data[stk-top]=x;

      return 1;

    }

}

4 出栈

int Pop(SeqStk *stk)

{

  if (EmptyStack(stk))

  {

    error("下溢");

    return 0;

  }

  else

    {

      stk->top--;

      return 1;

    }

}

5 取栈顶元素

DataType GetTop(SeqStk *stk)

{//取栈顶数据元素,栈顶数据元素通过参数返回

  if (EmptyStack(stk))

    return NULLData;

  else

    return stk->data[stk->top];

}

6 两栈相遇初始化

const int max=40;

typedef struct Dbstack

{

  DataType data[max];

  int top1,top2;

}DbStk;

两栈相遇时,top1=top2

判断上溢,top1+1=top2

当top1=0时栈1为空栈,top2=0时栈2 为空栈

栈的链接实现

链栈定义

typedef struct node

{

  DataType data;

  struct node *next;

}LkSk;

栈的基本运算在链栈上的实现算法

1 初始化

void InitStack(LkStk *LS)

{

  LS=(LkStk *)malloc(sizeof(LkStk));

  LS->next=NULL;//建立一个空栈

}

2 判栈空

int EmptyStack(LkStk *LS)

//若栈为空,则返回值1,否则返回值0

{

  if (LS->next == NULL)

    return 1;

  else

    return 0;

}

3 进栈-头插法

void Push(LkStk *LS,DataType x)

{

  LkStk *temp;

  temp=(LkStk *)malloc(sizeof(LkStk));

  temp->data=x;

  temp->next=LS->next;

  LS->next=temp;

}

4 出栈

int Pop(LkStk *LS)

//栈顶数据元素通过参数返回,它的直接后继成为新的栈顶

{

  LkStk *temp;

  if (! EmptyStack(LS))

  {

    temp=LS->next;

    LS->next=temp->next;

    free(temp);

    return 1;

  }

  else return 0;

}

5 取栈顶元素

DataType GetTop(LkStk *LS)

{

  if ( !EmptyStack(LS))

    return LS->next-data;

  else return NULLData;

6 栈的简单应用

 写一个算法,借助栈将带头结点的单链表逆置,教材67

 分析:扫描链表,将链表中数据元素依次进栈,然后,再一次扫描链表,同时依次进行出栈操作,将出栈的元素依次填到链表中去

void ReverseList(LKStk *head)

{

  LKStk *S;

  DataType x;

  InitStack(S);

  p=head->next;

  while (p != NULL)

  {

    Push(S,p->data);

    p=p->next;

  }

  p=head->next;

  while (!EmptyStack(S))

  {

    p->data=Gettop(S);

    Pop(S);

    p=p->next;

  }

}

队列的顺序实现

定义顺序队列

const int maxsize=20;

typedef struct seqqueue

{

  DataType data[maxsize];

  int front,rear;

}SeqQue;

SeqQue SQ;

循环队列

定义循环队列

typedef struct cycqueue

{

  DataType data[maxsize];

  int front,rear;

}CycQue;

CycQue SQ;

循环队列的基本运算

1 队列的初始化

void InitQueue(CycQue CQ)

{

  CQ.front=0;

  CQ.rear=0;

}

2 判队列空

int EmptyQueue(CycQue CQ)

{

  if (CQ.rear == CQ.front)

    return 1;//队列空返回1

  else return 0;

3 人队列

int EnQueue(CycQue CQ,DataType x)

{

  if ((CQ.rear+1) % maxsize == CQ.front)

    {

      error(“队列满");

      return 0;

    }

  else

    {

      CQ.rear=(CQ.rear+1)%maxsize;

      CQ.data[CQ.rear]=x;

      return 1;

    }

}

4 出队列

int OutQueue(CycQue CQ)

{

  if (EmptyQueue(CQ))

    {

      error(“队列空");

      return 0;

    }

  else

    {

      CQ.front=(CQ.front+1)%maxsize;

      return 1;

    }

}

5 取队列首元素

DataType GetHead(CycQue CQ)

{

  if (EmptyQueue(CQ))

    return NULLData;

  else

      return CQ.data[(CQ.front+1)%maxsize];

}

队列应用

在日常生活中,到银行办理业务时,往往需要排队等候,也就是按照“先到先服务”的原则。

在排队等候的过程中,主要有两件事:

(1)客户到达银行时,在电脑上取号;

(2)客户等待银行电脑语音报号,当报出某客户的序号时,客户到相应的窗口接受服务。

用类C语言算法描述如下:

void GetService()

{

  LkQue LQ;

  int n;

  char ch;

  InitQueue(&LQ)

  while(1)

  {

    printf("\n请输入命令:”);

    scanf("%c",&ch);

    switch(ch)

    {

      case 'A':

          printf("客户取号\n");

          scanf("%d",&n);

          EnQueue(&LQ,n);

          break;

      case 'N’:

          if (!EmptyQueue(LQ))

          {

            n=Gettop(LQ);

            OutQueue(&LQ);

            printf("号为 %d的客户接受服务",n);

          }

          else printf("无人等待服务\n");

          break;

      case 'Q':

          printf("排队等待的人依次接受服务\n");

          break;

     }

    if (ch=='Q')

      {

        while (!EmptyQueue(LQ))

        {

          n=Gettop(LQ);

          OutQueue(&LQ);

          printf("号为 %d的客服接受服务",n);

        }

        break;

      }

  }

}

数组

应用举例:设停车场(图3-32)内只有一个可停放几辆汽车的狭长通道,且只有一个大门可供汽车进出。汽车在停车场内按车辆到达时的先后顺序,依次由北向南排列(大门在最南端,最先到达的第一辆车停 放在车场的最北端),若车场内已停满汽车,则后来的汽车只能在门外的便道上等候,一日停车场内有车开走,则排在便道上的第一 辆车即可开入;当停车场内某辆车要离开时,由于停车场是狭长的通道,在它之后开入车场的车辆必须先开出去为它让路,待该辆车开出大门外后,为它让路的车辆再按原次序进入停车场。在这里假设汽车不能从便道上开走。试设计这样一个停车场管理程序(这里只是个假想的停车场管理)。

分析:汽车在停车场内进出方式和栈的特征相似。当有空位时,汽车进入停车场:停车场的汽车离开停车场时,车场内其他汽车为该辆汽车让路,是按栈的方式进行:汽年在便道上等候是按队列的方式进行。因此,将停车场设计成一 个栈,汽车让路也需要另一个栈来协助完成,汽车进出便道用队列来实现。本程序中,栈采用顺序存储结构,队列用链式存储结构,分别在头文件Seqstack.h和Lkqueue.h中定义。

//以下是头文件Seqstack.h

const int stacksize=40;

typedef struct SQstack

{

  int data[stacksize];

  int top;

}SQStackTp;

//以下为顺序栈的各运算符的函数

int InitStack(SeqStk *SQ)   //栈的初始化

{

  SQ->top=0;

  return 1;

}

int EmptyStack(SeqStk *SQ)

//若栈为空,则返回值1,否则返回值0

{

  if (SQ->top==0)

    return 1;

  else return 0;

}

int Push(SeqStk *SQ,int x)

{//进栈、若栈未满,元素x进栈stk中,否则提示出错信息

  if (SQ->top ==stacksize-1)

      return 0;

  else 

    {

      SQ->top++;

      SQ->data[SQ-top]=x;

      return 1;

    }

}

int Pop(SeqStk *stk)   //出栈

{

  if EmptyStack(SQ)

  {

    error("下溢");

    return 0;

  }

  else

    {

      SQ->top--;

      return 1;

    }

}

int GetTop(SeqStk *SQ)

{//取栈顶数据元素

  if (EmptyStack(SQ)

    return -1;//栈空,返回-1

  else return SQ->data[SQ->top];

}

 

//以下为头文件Lkqueue.h

typedef struct LinkQueueNode   //队列的存储结构

{

  int data;

  struct LinkQueueNode *next;

}LkQueNode;

typedef struct LkQueue

{

  LkQueNode *front,*rear;

}LkQue;

//以下为链队各运算的函数

IntQueue(LkQue *LQ)

{

  LkQueNode *p;

  p=(LkQueNode*)malloc(sizeof(LkQueNode));

  LQ->front=p;

  LQ->rear=p;

  (LQ->front)->next=NULL;

}

int EmptyQueue(LkQue LQ)

{

  if (LQ.rear==LQ.front)

    return 1;

  else return 0;

}

void EnQueue(LkQue *LQ,int x)   //入队列

{

  LkQueNode *p;

  p=(LkQueNode*)malloc(sizeof(LkQueNode));

  p->data=x;

  p-next=NULL;

  (LQ->rear)->next=p;

  LQ->rear=p;

}

int OutQueue(LkQue *LQ)   //出队列

{

  LkQueNode *s;

  if EmptyQueue(LQ);

    {

      error("队空");

      return 0;

    }

  else {

       s=(LQ->front)-next;

       (LQ->front)->next=s->next;

       if (s->next==NULL)

        LQ->rear=LQ->front;

       free(s);

       return 1;

     }

}

int GetHead(LkQue LQ)   //取队首元素

{

  LkQueNode *p;

  if EmptyQueue (LkQue LQ)

    return -1;

  else {

       p=LQ.front->next;

       return p->next;

     }

}

分析:汽车在停车场内进出方式和栈的特征相似。当有空位时,汽车进入停车场:停车场的汽车离开停车场时,车场内其他汽车为该辆汽车让路,是按栈的方式进行;汽车在便道 上等候是按队列的方式进行。因此,将停车场设计成 一个栈,汽车让路也需要另一个栈来协助完成,汽车进出便道用队列来实现。本程序中,栈采用顺序存储结构,队列用链式存储结构,分别在头文件Seqstack.h 和Lkqueue.h中定义。

下面是解决问题的应用程序

#include <stdio.h>

#include <alloc.h>

#include "Seqstack.h"

#include "LkQueue.h"

void main()

{

  SeqStk ps,ts;

  LkQue LQ;

  int out,number,temp;

  char ch;

  

  InitStack(&ps);    //初始化ps栈,它存储停车场车辆

  InitStack(&ts);     //初始化ts栈,它存储临时退出停车场的车辆

  InitQueue(&LQ);    //初始化LQ队列,它存储便道上车辆

  

  out=0;         //out=0表示在停车场未找到车号为number的车辆

             //out=1表示找到了

  scanf("%c",&ch);     //读入命令

  scanf("%d",&number); //读入车号,当车号为0时程序结束

  while (number>0);

  {

    switch(ch)

    {

      case 'A' :  //车辆进入停车场

          if (ps.top==stacksize-1)//停车场满

          {

            EnQueue(&LQ,number);

            printf("停车场已满! 第%d号车入便道!\n",number);

          }

          else {

               Push(&ps,number);

               printf("第 %d号车入车场!\n",number);

             }

          break;

      case 'D':  //车辆开出停车场

          while (!EmptyStack(ps))

          {

            temp=Gettop(ps);

            Pop(&ps);

            if (temp!=number)

              Push(&ts,temp);

            else {

                 printf("第%d号离开停车场!\n",number);

                 out=1;

                 break;

               }

          }

          while (!EmptyStack(ts))   //临时开出停车场的车开回停车场

          {

            temp=Gettop(ts);

            Pop(&ts);

            Push(&ps,temp);

          }

          if (out && !EmptyQueue(LQ))

          {

            temp=GetHead(&LQ);

            OutQueue(&LQ);

            printf("第%d号车由便道->停车场!\m",temp);

            Push(&ps,temp);

          }

          out=0;

          break;

    }

    scanf("%c",&ch);    //继续读入命令

    scanf("%d",&number);   //继续读入车号

  }

}

 

 posted on 2021-05-30 21:48  HuJiao粉  阅读(92)  评论(0)    收藏  举报