算法导论之六栈与队列

1.在栈中,被删除的是最近插入的元素,其实现的是后进先出(LIFO)策略,在队列中,删除的是在集合中存在时间最长的那个元素,其实现的是先进先出(FIFO)策略。

2.可用一个数组来实现最多容纳个元素的栈,其中有一个属性,指向最新插入的元素,如果试图对一个空栈执行弹出操作,则称栈下溢,如果超过了,则称栈上溢。

3.几种栈操作的伪代码:

       STACK_EMPTY(S)

              if  = =0

                     return TRUE

              else return FALSE

 

       PUSH(S, x)

               =  +  1

              S[] = x

 

       POP(S)

              if STACK_EMPTY(S)

                     error "underflow"

              else  =  - 1

                     return S[+1]

4. 队列有队头和队尾,当有一个元素入队时,它被放在队尾的位置,而出队的元素则总是排在对头的那个。利用数组可实现最多容纳个元素的队列。属性指向队头元素,属性指向下一个新元素要插入的位置。当时,队列为空,当时,队列为满。

5. 有关队列的伪代码,省略了对下溢和上溢的检查

       ENQUEUE(Q,x)

              Q[] = x

              if ==

                      =  1

              else =  + 1

 

       DEQUEUE(Q)

              x= Q[]

              if==

                     = 1

              else= + 1

              returnx

6. 顺序栈的应用

#include <stdio.h>

#include <stdlib.h>

 

#define OK 1

#define ERROR 0

#define TRUE 1

#define FALSE 0

#define STACK_INIT_SIZE 100

#define STACKINCREMENT 10

 

typedef int Status;  //函数返回状态

typedef char SElemType;      //栈元素类型

typedef struct

{

       SElemType*base;

       SElemType*top;

       intstacksize;

}SqStack;       //栈结构定义

 

//构造一个空栈

Status InitStack(SqStack *S)

{

       S->base=(SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElemType));

       if(!S->base)

       {

              printf("分配内存失败.\n");

              exit(0);

       }

       S->top=S->base;

       S->stacksize=STACK_INIT_SIZE;

       returnOK;

}

 

//销毁S,S不再存在

Status DestroyStack(SqStack *S)

{

       if(!S)

       {

              printf("指针为空,释放失败.\n");

              exit(0);

       }

       free(S);

       returnOK;

}

 

//将S置为空栈

Status ClearStack(SqStack *S)

{

       if(!S)

       {

              returnFALSE;

       }

       S->top=S->base;    //直接将栈顶指针指向栈底

       returnOK;

}

 

//判断S是否为空栈

Status StackEmpty(SqStack S)

{

       if(S.base==S.top)

       {

              returnTRUE;

       }

       else

              returnFALSE;

}

 

//返回栈的长度

int StackLength(SqStack S)

{

       returnS.stacksize;

}

 

//若栈不为空,则用e返回S的栈顶元素,否则返回false

Status GetTop(SqStack S,SElemType*e)

{

       if(S.top==S.base)

       {

              printf("栈为空.\n");

              returnFALSE;

       }

       else

       {

              e=S.top-1;

              printf("栈顶元素:%c\n",*e);

              returnOK;

       }

}

 

//插入元素e为新的栈顶元素

Status Push(SqStack *S,SElemTypee)

{

       //栈已满,追加存储空间

       if((S->top-S->base)>=S->stacksize)

       {

              S->base=(SElemType*)realloc(S->base,(S->stacksize+STACK_INIT_SIZE)*sizeof(SElemType));

              if(!S->base)

              {

                     printf("重新申请空间失败.\n");

                     exit(0);

              }

              S->top=S->base+S->stacksize;      //更改栈顶指针

              S->stacksize+=STACKINCREMENT;

       }

       *S->top++=(*e);

       returnOK;

}

 

//若栈S不为空,则删除S的栈顶元素,用e返回其值,并返回OK,否则返回ERROR

Status Pop(SqStack *S,SElemType*e)

{

       if(S->top=S->base)

       {

              printf("栈为空.\n");

              returnERROR;

       }

       e=--S->top;

       returnOK;

}

 

//从栈底到栈顶依次对每个元素进行访问

Status StackTraverse(constSqStack *S)

{

       SElemType*p=S->base;

       if(S->base==S->top)

       {

              printf("栈为空.\n");

              returnERROR;

       }

       printf("栈中元素:");

       while(p!=S->top)

       {

              printf("%c",*p++);

       }

       printf("\n");

       returnOK;

}

 

 

//==============交互处理===============//

void PrintMsg(){//输出操作提示信息 

       printf("--Welcome--\n"); 

       printf("请输入您要进行的操作:\n"); 

       printf("I:元素入栈\n"); 

       printf("O:元素出栈\n"); 

       printf("A:查看栈中所有元素\n"); 

       printf("C:清空栈\n"); 

       printf("T:查看栈顶元素\n"); 

       printf("L:查看栈空间\n"); 

       printf("Q:退出\n"); 

       printf("others:donothing.\n"); 

       printf(">>"); 

}

 

char getOption(){//获取用户输入操作 

       charinput; 

       scanf("%c",&input); 

       flushall(); 

       input=toupper(input); 

       returninput; 

}

SElemType getElemInput(){//获得入栈元素 

       SElemTypee; 

       printf("请输入一个字符:"); 

       scanf("%c",&e); 

       flushall(); 

       returne; 

}

 

int main() 

       charop; 

       SqStackstack;//栈 

       SElemTypee;//元素 

       PrintMsg(); 

       InitStack(&stack); 

       while(op=getOption()){ 

              if(op=='Q')//退出 

                     break; 

              switch(op){ 

              case'I'://入栈 

                     e=getElemInput(); 

                     Push(&stack,e); 

                     break; 

              case'O'://出栈 

                     Pop(&stack,&e); 

                     break; 

              case'A'://遍历栈中元素 

                     StackTraverse(&stack); 

                     break; 

              case'C'://清空栈 

                     ClearStack(&stack); 

                     break; 

              case'T'://获取栈顶 

                     GetTop(stack,&e); 

                     break; 

              case'L'://获取栈空间 

                     printf("栈空间:%d\n",StackLength(stack)); 

                     break; 

              default: 

                     break; 

              }//switch 

              printf(">>"); 

       }//while 

       printf("--Byebye--\n"); 

       return0; 

 

7. 队列的应用:

#include "stdio.h"

#include "stdlib.h"

#include "io.h"

#include "math.h"

#include "time.h"

 

#define OK 1

#define ERROR 0

#define TRUE 1

#define FALSE 0

#define MAXSIZE 20

 

typedef int Status;

typedef int QElemType;

 

//循环队列的顺序存储结构

typedef struct

{

    QElemType data[MAXSIZE];   

    int front;        //头指针

    int rear;       //尾指针

}SqQueue;

 

Status visit(QElemType c)

{

    printf("%d",c);

   return OK;

}

 

//初始化一个空队列Q

Status InitQueue(SqQueue *Q)

{

    Q->front=0;

    Q->rear=0;

    return OK;

}

 

//将Q清为空队列

Status ClearQueue(SqQueue *Q)

{

    Q->front=Q->rear=0;

    return OK;

}

 

//若队列Q为空队列,则返回TRUE,否则返回FALSE

Status QueueEmpty(SqQueue Q)

{

    if(Q.front==Q.rear)

        return TRUE;

    else

        return FALSE;

}

 

//返回Q的元素个数,也就是队列的当前长度

int QueueLength(SqQueue Q)

{

    return (Q.rear-Q.front+MAXSIZE)%MAXSIZE;

}

 

//若队列不空,则用e返回Q的队头元素,并返回OK,否则返回FALSE

Status GetHead(SqQueueQ,QElemType *e)

{

    if(Q.front==Q.rear)

        return ERROR;

    else

        *e=Q.data[Q.front];

    return OK;

}

 

//若队列未满,则插入元素e为Q新的队尾元素

Status EnQueue(SqQueue*Q,QElemType e)

{

    if((Q->rear+1)%MAXSIZE==Q->front)

        return ERROR;

    Q->data[Q->rear]=e;

    Q->rear=(Q->rear+1)%MAXSIZE;

 

    return OK;

}

 

//若队列不空,则删除 Q中队头元素,用e返回其值

Status DeQueue(SqQueue*Q,QElemType *e)

{

    if(Q->front==Q->rear)

        return ERROR;

    else

        *e=Q->data[Q->front];

        Q->front=(Q->front+1)%MAXSIZE;

 

    return OK;

}

 

//从队头到队尾依次对队列Q每个元素输出

Status QueueTraverse(SqQueue Q)

{

    int i;

    i=Q.front;

    while((i+Q.front)!=Q.rear)

    {

        visit(Q.data[i]);

        i=(i+1)%MAXSIZE;

    }

    printf("\n");

    return OK;

}

 

int main()

{

    Status j;

    int i=0,l;

    QElemType d;

    SqQueue Q;

    InitQueue(&Q);

    printf("初始化队列后,队列空否?%u(1:空0:否)\n",QueueEmpty(Q));

 

    printf("请输入整型队列元素(不超过%d个),-1为提前结束符:",MAXSIZE-1);

 

    do

    {

        d=i+100;

        if(d==-1)

            break;

        i++;

        EnQueue(&Q,d);

    }while(i<MAXSIZE-1);

 

    printf("队列长度为:%d\n",QueueLength(Q));

    printf("现在队列空否?%u(1:空0:否)\n",QueueEmpty(Q));

    printf("连续%d次由队头删除元素,队尾插入元素:\n",MAXSIZE);

    for(l=1;l<=MAXSIZE;l++)

    {

        DeQueue(&Q,&d);

        printf("删除的元素是%d,插入的元素:%d\n",d,l+1000);

        /* scanf("%d",&d); */

        d=l+1000;

        EnQueue(&Q,d);

    }

    l=QueueLength(Q);

 

    printf("现在队列中的元素为: \n");

    QueueTraverse(Q);

    printf("共向队尾插入了%d个元素\n",i+MAXSIZE);

    if(l-2>0)

        printf("现在由队头删除%d个元素:\n",l-2);

    while(QueueLength(Q)>2)

    {

        DeQueue(&Q,&d);

        printf("删除的元素值为%d\n",d);

    }

 

    j=GetHead(Q,&d);

    if(j)

        printf("现在队头元素为:%d\n",d);

    ClearQueue(&Q);

    printf("清空队列后, 队列空否?%u(1:空0:否)\n",QueueEmpty(Q));

    return 0;

}

 

 

//其链表结构

#include "stdio.h"   

#include"stdlib.h"  

#include "io.h" 

#include "math.h" 

#include "time.h"

 

#define OK 1

#define ERROR 0

#define TRUE 1

#define FALSE 0

#define MAXSIZE 20 /* 存储空间初始分配量*/

 

typedef int Status;

 

typedef int QElemType; /*QElemType类型根据实际情况而定,这里假设为int */

 

typedef struct QNode    /* 结点结构 */

{

  QElemType data;

  struct QNode *next;

}QNode,*QueuePtr;

 

typedef struct            /* 队列的链表结构 */

{

  QueuePtr front,rear; /* 队头、队尾指针 */

}LinkQueue;

 

Status visit(QElemType c)

{

    printf("%d ",c);

    return OK;

}

 

/* 构造一个空队列Q */

Status InitQueue(LinkQueue *Q)

{

   Q->front=Q->rear=(QueuePtr)malloc(sizeof(QNode));

    if(!Q->front)

        exit(OVERFLOW);

    Q->front->next=NULL;

    return OK;

}

 

/* 销毁队列Q */

Status DestroyQueue(LinkQueue *Q)

{

    while(Q->front)

    {

         Q->rear=Q->front->next;

         free(Q->front);

         Q->front=Q->rear;

    }

    return OK;

}

 

/* 将Q清为空队列*/

Status ClearQueue(LinkQueue *Q)

{

    QueuePtr p,q;

    Q->rear=Q->front;

    p=Q->front->next;

    Q->front->next=NULL;

    while(p)

    {

         q=p;

         p=p->next;

         free(q);

    }

    return OK;

}

 

/* 若Q为空队列,则返回TRUE,否则返回FALSE*/

Status QueueEmpty(LinkQueue Q)

{

    if(Q.front==Q.rear)

        return TRUE;

    else

        return FALSE;

}

 

/* 求队列的长度 */

int QueueLength(LinkQueue Q)

{

    int i=0;

    QueuePtr p;

    p=Q.front;

    while(Q.rear!=p)

    {

         i++;

         p=p->next;

    }

    return i;

}

 

/* 若队列不空,则用e返回Q的队头元素,并返回OK,否则返回ERROR*/

Status GetHead(LinkQueue Q,QElemType*e)

{

    QueuePtr p;

    if(Q.front==Q.rear)

        return ERROR;

    p=Q.front->next;

    *e=p->data;

    return OK;

}

 

 

/* 插入元素e为Q的新的队尾元素*/

Status EnQueue(LinkQueue*Q,QElemType e)

{

    QueuePtr s=(QueuePtr)malloc(sizeof(QNode));

    if(!s) /* 存储分配失败 */

        exit(OVERFLOW);

    s->data=e;

    s->next=NULL;

    Q->rear->next=s;    /* 把拥有元素e的新结点s赋值给原队尾结点的后继,见图中① */

    Q->rear=s;        /* 把当前的s设置为队尾结点,rear指向s,见图中②*/

    return OK;

}

 

/* 若队列不空,删除Q的队头元素,用e返回其值,并返回OK,否则返回ERROR*/

Status DeQueue(LinkQueue*Q,QElemType *e)

{

    QueuePtr p;

    if(Q->front==Q->rear)

        return ERROR;

    p=Q->front->next;        /* 将欲删除的队头结点暂存给p,见图中①*/

    *e=p->data;                /* 将欲删除的队头结点的值赋值给e */

    Q->front->next=p->next;/* 将原队头结点的后继p->next赋值给头结点后继,见图中② */

    if(Q->rear==p)        /* 若队头就是队尾,则删除后将rear指向头结点,见图中③*/

        Q->rear=Q->front;

    free(p);

    return OK;

}

 

/* 从队头到队尾依次对队列Q中每个元素输出*/

Status QueueTraverse(LinkQueue Q)

{

    QueuePtr p;

    p=Q.front->next;

    while(p)

    {

         visit(p->data);

         p=p->next;

    }

    printf("\n");

    return OK;

}

 

int main()

{

    int i;

    QElemType d;

    LinkQueue q;

    i=InitQueue(&q);

    if(i)

        printf("成功地构造了一个空队列!\n");

    EnQueue(&q,-5);

    EnQueue(&q,5);

    EnQueue(&q,10);

    printf("插入3个元素(-5,5,10)后,队列的长度为%d\n",QueueLength(q));

    printf("队列的元素依次为:");

    QueueTraverse(q);

    i=GetHead(q,&d);

    if(i==OK)

     printf("队头元素是:%d\n",d);

    DeQueue(&q,&d);

    printf("删除了队头元素%d\n",d);

    i=GetHead(q,&d);

    if(i==OK)

        printf("新的队头元素是:%d\n",d);

    ClearQueue(&q);

    printf("清空队列后,q.front=%u q.rear=%uq.front->next=%u\n",q.front,q.rear,q.front->next);

    DestroyQueue(&q);

    printf("销毁队列后,q.front=%uq.rear=%u\n",q.front, q.rear);

   

    return 0;

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mengrennwpu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值