06栈[数据结构学习笔记](注释比代码多)

·相关概念

  1. 定义:限定只能在表的一端进行插入和删除运算的线性表(比如手电筒存取电池的操作)

  2. 逻辑结构:与线性表相同,仍为一对一关系。

  3. 存储结构:顺序栈和链式栈都可,但顺序栈更常用

  4. 运算规则:只能在栈顶运算,后进先出(LIFO)原则.与线性表不同(随机存取)。

·具体实现

顺序栈:

  1. 顺序栈的表示
#define MAXSIZE 100
typedef struct {
    int *base;   // 栈底指针
    int *top;    // 栈顶指针
    int stacksize;  // 栈可用最大容量
}SqStack;
  1. 顺序栈的初始化(即构造一个空栈)
Status InitStack(SqStack &S){
    S.base=(int*)malloc(MAXSIZE*sizeof(int));  // 为栈底指针开辟地址(malloc不再赘述)
    if(!S.base)exit(OVERFLOW);  // 如果base地址为0则表示没有分配成功
    S.top=S.base;   //栈顶指针等于栈底指针则为空栈
    S.stacksize=MAXSIZE; //栈的最大容量
    return OK;
}
  1. 顺序栈的清空与销毁
// 清空顺序栈
Status ClearStack(SqStack &S){
    if(S.base)S.top=S.base; //如果栈底不为空就令栈顶指针=栈底指针则为空栈
    return OK;
}

// 销毁顺序栈(与清空相比,将地址释放)
Status DestroyStack(SqStack &S){
    if(S.base){ //若是空栈则销毁
        delete S.base;
        S.stacksize=0;
        S.base=S.top=NULL;
    }
    return OK;
}
  1. 顺序栈的入栈

·算法思路:

  1. 判读是否栈满,若满则报错(上溢)
  2. 元素e压入栈顶指针
  3. 指针++指向下一元素
//  顺序栈的入栈
Status Push(SqStack &S, int e){
    if(S.top-S.base==S.stacksize) return ERROR;   //判读栈满
    *S.top=e;   //将元素e填入栈此时的顶部
    S.top++;    //让指针加1表示指向下一空间
    return OK;
}
  1. 顺序栈的出栈

·算法思路:

  1. 判断是否栈空,若空则报错(下溢)
  2. 获取栈顶元素,用e返回其指
  3. 栈顶指针–指向下一元素
// 顺序栈的出栈
Status Pop(SqStack &S, int &e){
    if(S.top==S.base) return ERROR; //判断是否为空栈
    S.top--;    //令top指向栈顶元素
    e=*S.top;
    return OK;
}

链栈:

概念:链栈是元素受限的单链表,只能在链表头部进行操作

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4MbsaaY4-1639484159377)(img.png)]

注意(一般情况下):
· 链表的头指针就是栈顶,不需要头结点
· 基本不存在栈满的情况
· 空栈相当于头指针指向空

  1. 链栈的结点定义:
// 链栈的结点
typedef struct StackNode{
    int data;
    struct StackNode *next; //嵌套定义
}StackNode,*LinkStack;
  1. 链栈的初始化
// 链栈的初始化(构建空栈)
Status InitStack(LinkStack &S){
    S=NULL;
    return OK ;
}
  1. 链栈的入栈

·算法思路:

  1. 生成一个新结点p,并且p指针指向该结点
  2. 为新结点赋值
  3. 让S指向新的栈顶
// 链栈的入栈
Status Push(LinkStack &S, int e){
    StackNode *p;   //定义指向p结点的指针
    p = (LinkStack) malloc(sizeof(LinkStack));//开辟新结点
    p->data=e;  
    p->next=S;
    S=p;
    return OK;
}
  1. 链栈的出栈

·算法思路:

  1. 判断是否栈空,若空则报错(下溢)
  2. 获取栈顶元素,用e返回其值
  3. 栈顶指针–指向下一元素
// 链栈的出栈
Status Pop(LinkStack &S,int &e){
    if(S==NULL) return ERROR;   //  判断是否为空
    e = S->data;    // 获取栈顶元素的指,e返回其值
    StackNode *p;   //定义指向p结点的指针
    p = S;          //让结点指针p指向出栈的结点,以便删除
    S=S->next;      //栈顶指针指向下一个元素
    delete p;   //将空结点删除释放空间
    return OK;
}

5.取栈顶元素的值

int GetTop(LinkStack S){
    if(S!=NULL)
        return S->data;
}

栈与递归

递归的定义:

  1. 对象递归: 若一个对象包含它自己,或用它自己给自己定义,则这个对象是递归的。
  2. 过程递归: 若一个过程直接或间接的调用自己,则为过程递归

递归的用途:

  1. 定义数学函数:阶乘等
  2. 具有递归特性的数据结构:二叉树,广义表
  3. 递归求解问题:迷宫问题,汉诺塔问题

递归问题----用分治法求解

一般形式如下:

void p(参数){
    if(递归结束条件) 可直接求解步骤;----基本项
    else p(较小参数);----归纳项
}

在这里插入图片描述

// 递归求阶乘
int DiGuDemo(int n){
    if(n==1) return 1;
    else n*=DiGuDemo(n-1);
}

在这里插入图片描述

递归的优缺点

优点:结构清晰,程序易读
缺点:每次调用要生成工作记录,保存状态信息,入栈;返回时要出栈,恢复状态信息,时间开销大。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

阿明同学

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

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

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

打赏作者

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

抵扣说明:

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

余额充值