C语言数据结构(大话数据结构——笔记2)第四章:栈与队列

Posted Dontla

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言数据结构(大话数据结构——笔记2)第四章:栈与队列相关的知识,希望对你有一定的参考价值。

文章目录

第四章:栈与队列(115)

在这里插入图片描述

栈顶与栈底,空栈,后进先出 Last in first out(LIFO结构)(117)

进栈、压栈、入栈:栈的插入操作;出栈、弹栈:栈的删除操作(118)

在这里插入图片描述

push、pop,压栈和弹栈(进栈和出栈 )(119)

在这里插入图片描述

栈的顺序存储结构:顺序栈(数组实现)(120)

在这里插入图片描述

两栈共享空间(122)

在这里插入图片描述

最好是相同的数据类型共享(124)

栈的链式存储结构(链栈)(125)

链栈不需要头结点(创建一个栈链结构,结构中包含指向栈顶top的指针和结点数量)
在这里插入图片描述
在这里插入图片描述

栈的链式存储结构——进栈push操作:(126)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

栈的链式存储结构——出栈pop操作:(127)

在这里插入图片描述
在这里插入图片描述

顺序栈和链栈的优缺点:(128)

在这里插入图片描述

栈的作用:简化了程序设计的问题,划分了不同关注层次,使得思考范围缩小,更加聚焦于我们要解决的问题核心。(128)

栈的应用:递归(128)

斐波那契数列实现(129)

斐波那契数列:前面两项之和,构成了后一项
在这里插入图片描述

传统迭代方法

在这里插入图片描述

递归算法

在这里插入图片描述
在这里插入图片描述

递归函数的定义(131)

一个直接调用自己,或通过一系列的调用语句间接地调用自己的函数,称为递归函数

递归与迭代的区别(132)

在这里插入图片描述

栈在递归操作中的作用(132)

在这里插入图片描述

栈的应用——四则运算表达式求值(132)

后缀(逆波兰)(reverse polish notation, RPN)表示法(133)
后缀表达式(133)
中缀表达式(标准四则运算表达式)转后缀表达式(136)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

队列的定义(139)

队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表

先进先出(first in first out, FIFO),允许插入的一端称为队尾,允许删除的一端称为队头

队列的抽象数据类型(140)

在这里插入图片描述

循环队列(顺序存储结构)(140)

队列顺序存储的缺点(140)

出队时间复杂度高(O(n))

front与rear指针(141)

在这里插入图片描述

假溢出的概念(142)

不循环所存在的问题:后面满了,但前面空着,不会把元素加到前面

循环队列定义(142)

头尾相接的顺序存储结构

如何判断循环队列是空还是满?(143)

在这里插入图片描述
假设队列的最大尺寸是QueueSize,则队列满的条件是(rear + 1)% QueueSize == front,%为取模符号

通用计算队列长度公式(144)

(rear - front + QueueSize)% QueueSize

循环队列顺序存储结构代码(144)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

顺序存储结构循环队列缺点:可能会溢出(145)

队列的链式存储结构及实现(其实就是线性表的单链表修改版,只能尾进头出)(链队列)(145)

队头指针指向队列头结点,队尾指针指向终端结点
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

队列的链式存储结构——入队操作

入队操作:在链表尾部插入结点
在这里插入图片描述
在这里插入图片描述

队列的链式存储结构——出队操作

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(顺序存储结构)循环队列与链队列的对比(链队列每次malloc申请和释放结点也会存在一定的时间开销)(148)

在这里插入图片描述

栈与队列总结(149)

在这里插入图片描述

本章配套代码

顺序栈

#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 SElemType; /* SElemType类型根据实际情况而定,这里假设为int */

/* 顺序栈结构 */
typedef struct
{
        SElemType data[MAXSIZE];
        int top; /* 用于栈顶指针 */
}SqStack;

Status visit(SElemType c)
{
        printf("%d ",c);
        return OK;
}

/*  构造一个空栈S */
Status InitStack(SqStack *S)
{ 
        /* S.data=(SElemType *)malloc(MAXSIZE*sizeof(SElemType)); */
        S->top=-1;
        return OK;
}

/* 把S置为空栈 */
Status ClearStack(SqStack *S)
{ 
        S->top=-1;
        return OK;
}

/* 若栈S为空栈,则返回TRUE,否则返回FALSE */
Status StackEmpty(SqStack S)
{ 
        if (S.top==-1)
                return TRUE;
        else
                return FALSE;
}

/* 返回S的元素个数,即栈的长度 */
int StackLength(SqStack S)
{ 
        return S.top+1;
}

/* 若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR */
Status GetTop(SqStack S,SElemType *e)
{
        if (S.top==-1)
                return ERROR;
        else
                *e=S.data[S.top];
        return OK;
}

/* 插入元素e为新的栈顶元素 */
Status Push(SqStack *S,SElemType e)
{
        if(S->top == MAXSIZE -1) /* 栈满 */
        {
                return ERROR;
        }
        S->top++;				/* 栈顶指针增加一 */
        S->data[S->top]=e;  /* 将新插入元素赋值给栈顶空间 */
        return OK;
}

/* 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR */
Status Pop(SqStack *S,SElemType *e)
{ 
        if(S->top==-1)
                return ERROR;
        *e=S->data[S->top];	/* 将要删除的栈顶元素赋值给e */
        S->top--;				/* 栈顶指针减一 */
        return OK;
}

/* 从栈底到栈顶依次对栈中每个元素显示 */
Status StackTraverse(SqStack S)
{
        int i;
        i=0;
        while(i<=S.top)
        {
                visit(S.data[i++]);
        }
        printf("\\n");
        return OK;
}

int main()
{
        int j;
        SqStack s;
        int e;
        if(InitStack(&s)==OK)
                for(j=1;j<=10;j++)
                        Push(&s,j);
        printf("栈中元素依次为:");
        StackTraverse(s);
        Pop(&s,&e);
        printf("弹出的栈顶元素 e=%d\\n",e);
        printf("栈空否:%d(1:空 0:否)\\n",StackEmpty(s));
        GetTop(s,&e);
        printf("栈顶元素 e=%d 栈的长度为%d\\n",e,StackLength(s));
        ClearStack(&s);
        printf("清空栈后,栈空否:%d(1:空 0:否)\\n",StackEmpty(s));
        
        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 SElemType; /* SElemType类型根据实际情况而定,这里假设为int */


/* 两栈共享空间结构 */
typedef struct 
{
        SElemType data[MAXSIZE];
        int top1;	/* 栈1栈顶指针 */
        int top2;	/* 栈2栈顶指针 */
}SqDoubleStack;


Status visit(SElemType c)
{
        printf("%d ",c);
        return OK;
}

/*  构造一个空栈S */
Status InitStack(SqDoubleStack *S)
{ 
        S->top1=-1;
        S->top2=MAXSIZE;
        return OK;
}

/* 把S置为空栈 */
Status ClearStack(SqDoubleStack *S)
{ 
        S->top1=-1;
        S->top2=MAXSIZE;
        return OK;
}

/* 若栈S为空栈,则返回TRUE,否则返回FALSE */
Status StackEmpty(SqDoubleStack S)
{ 
        if (S.top1==-1 && S.top2==MAXSIZE)
                return TRUE;
        else
                return FALSE;
}

/* 返回S的元素个数,即栈的长度 */
int StackLength(SqDoubleStack S)
{ 
        return (S.top1+1)+(MAXSIZE-S.top2);
}

/* 插入元素e为新的栈顶元素 */
Status Push(SqDoubleStack *S,SElemType e,int stackNumber)
{
        if (S->top1+1==S->top2)	/* 栈已满,不能再push新元素了 */
                return ERROR;	
        if (stackNumber==1)			/* 栈1有元素进栈 */
                S->data[++S->top1]=e; /* 若是栈1则先top1+1后给数组元素赋值。 */
        else if (stackNumber==2)	/* 栈2有元素进栈 */
                S->data[--S->top2]=e; /* 若是栈2则先top2-1后给数组元素赋值。 */
        return OK;
}

/* 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR */
Status Pop(SqDoubleStack *S,SElemType *e,int stackNumber)
{ 
        if (stackNumber==1) 
        {
                if (S->top1==-1) 
                        return ERROR; /* 说明栈1已经是空栈,溢出 */
                *e=S->data[S->top1--]; /* 将栈1的栈顶元素出栈 */
        }
        else if (stackNumber==2)
        { 
                if (S->top2==MAXSIZE) 
                        return ERROR; /* 说明栈2已经是空栈,溢出 */
                *e=S->data[S->top2++]; /* 将栈2的栈顶元素出栈 */
        }
        return OK;
}

Status StackTraverse(SqDoubleStack S)
{
        int i;
        i=0;
        while(i<=S.top1)
        {
                visit(S.data[i++]);
        }
        i=S.top2;
        while(i<MAXSIZE)
        {
                visit(S.data[i++]);
        }
        printf("\\n");
        return OK;
}

int main()
{
        int j;
        SqDoubleStack s;
        int e;
        if(InitStack(&s)==OK)
        {
                for(j=1;j<=5;j++)
                        Push(&s,j,1);
                for(j=MAXSIZE;j>=MAXSIZE-2;j--)
                        Push(&s,j,2);
        }

        printf("栈中元素依次为:");
        StackTraverse(s);

        printf("当前栈中元素有:%d \\n",StackLength(s));

        Pop(&s,&e,2);
        printf("弹出的栈顶元素 e=%d\\n",e);
        printf("栈空否:%d(1:空 0:否)\\n",StackEmpty(s));

        for(j=6;j<=MAXSIZE-2;j++)
                Push(&s,j,1);

        printf("栈中元素依次为:");
        StackTraverse(s);

        printf("栈满否:%d(1:否 0:满)\\n",Push(&s,100,1));

        
        ClearStack(&s);
        printf("清空栈后,栈空否:%d(1:空 0:否)\\n",StackEmpty(s));
        
        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 SElemType; /* SElemType类型根据实际情况而定,这里假设为int */


/* 链栈结构 */
typedef struct StackNode
{
        SElemType data;
        struct StackNode *next;
}StackNode,*LinkStackPtr;


typedef struct
{
        LinkStackPtr top;
        int count;
}LinkStack;

Status visit(SElemType c)
{
        printf("%d ",c);
        return OK;
}

/*  构造一个空栈S */
Status InitStack(LinkStack *S)
{ 
        S->top = (LinkStackPtr)malloc(sizeof(StackNode));
        if(!S->top)
                return ERROR;
        S->top=NULL;
        S->count=0;
        return OK;
}

/* 把S置为空栈 */
Status ClearStack(LinkStack *S)
{ 
        LinkStackPtr p,q;
        p=S->top;
        while(p)
        {  
                q=p;
                p=p->next;
                free(q);
        } 
        S->count=0;
        return OK;
}

/* 若栈S为空栈,则返回TRUE,否则返回FALSE */
Status StackEmpty(LinkStack S)
{ 
        if (S.count==0)
                return TRUE;
        else
                return FALSE;
}

/* 返回S的元素个数,即栈的长度 */
int StackLength(LinkStack S)
{ 
        return S.count;
}

/* 若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR */
Status GetTop(LinkStack S,SElemType *e)
{
        if (S.top==NULL)
                return ERROR;
        else
                *e=S.top->data;
        return OK;
}

/* 插入元素e为新的栈顶元素 */
Status Push(LinkStack *S,SElemType e)
{
        LinkStackPtr s=(LinkStackPtr)malloc(sizeof(StackNode)); 
        s->data=e; 
        s->next=S->top;	/* 把当前的栈顶元素赋值给新结点的直接后继,见图中① */
        S->top=s;         /* 将新的结点s赋值给栈顶指针,见图中② */
        S->count++;
        retu

以上是关于C语言数据结构(大话数据结构——笔记2)第四章:栈与队列的主要内容,如果未能解决你的问题,请参考以下文章

C语言数据结构(大话数据结构——笔记1)数据结构绪论算法线性表

C语言数据结构(大话数据结构——笔记4)第六章:树

C语言数据结构(大话数据结构——笔记3)第五章:串(字符串)

《大话数据结构》笔记(4-1)--栈与队列:栈

《学习JavaScript数据结构与算法》 第四章笔记 栈

数据结构复习笔记————栈的常用接口实现(c语言)