栈的知识点总结(顺序栈和链栈)——应用:数制转换

目录

一、栈的逻辑结构

1.栈定义

2.栈与线性表的区别与联系

3.栈的相关运算

4.要对栈状态进行标示,仅需要一个参数即可。

二、顺序栈

1.顺序栈数据结构

2.顺序栈初始化

3.判断栈空和栈满

4.压栈

5.弹栈

6.取栈顶元素

7.顺序栈进行数制转换,实现10进制转8进制

三、链栈

1.链栈数据结构定义

2.初始化

3.判断栈空

4.压栈

5.弹栈

6.链栈进行数制转换,实现10进制转8进制


顺序表相关知识:https://blog.csdn.net/qq_41291253/article/details/89317523

链表相关知识:https://blog.csdn.net/qq_41291253/article/details/89218736

new 和 malloc区别:https://www.cnblogs.com/ywliao/articles/8116622.html

一、栈的逻辑结构

1.栈定义

栈(Stack)是一种特殊的线性表,它所有的插入和删除都限制在表的同一端进行。

栈中允许进行插入、删除操作的一端叫做栈顶(Top),另一端则叫做栈底(Bottom)。当栈中没有元素时,称之为空栈。栈的插入运算通常称为压栈、进栈或入栈(Push),栈的删除运算通常称为弹栈或出栈(Pop)。示意图如下

栈的知识点总结(顺序栈和链栈)——应用:数制转换_第1张图片

2.栈与线性表的区别与联系

(1)栈是特殊的线性表

(2)栈的插入与删除运算只能在栈顶进行,而线性表的插入和删除运算可在线性表中的任意位置进行

3.栈的相关运算

(1)栈的初始化操作:建立一个空栈 S。

(2)判栈空:判断栈是否为空。

(3)取栈顶元素:取得栈顶元素的值。

(4)压栈:在栈S中插入元素e,使其成为新的栈顶元素。

(5)弹栈:删除栈 S的栈顶元素。

4.要对栈状态进行标示,仅需要一个参数即可。

在栈的大小已经确定的前提下,有栈空、栈满、非空非满三种情况。根据栈的定义,每次进栈的数据元素,都放在栈顶元素之前而成为新的栈顶元素,每次退栈的数据元素都是当前栈顶元素,所以栈中内容的变化只需要一个栈顶指针的指示即可。

 

二、顺序栈

1.顺序栈数据结构

栈的顺序存储结构需要使用一个数组和一个整形变量来实现。利用数组来顺序存储栈中的所有元素,利用整形变量来存储栈顶元素的下标位置。

/*=====================================
 函数功能:栈结构体定义
 函数输入:无
 函数输出:无
 ====================================*/
typedef struct Stack
{
    int data[Stack_Size];                 //顺序栈(数组)大小
    int top;                              //栈顶位置(栈顶在数组中的下标)
}SeqStack;

2.顺序栈初始化

对栈初始化,将栈顶指针置为-1;

/*=====================================
 函数功能:顺序栈置空栈(初始化)
 函数输入:顺序栈地址
 函数输出:无
 ====================================*/
void initialize_SqStack(SeqStack *s)      //要更改栈内数据,需要传址调用,或者采取引用方式
{
    s->top = -1;
}

3.判断栈空和栈满

判断栈空,查找栈中是否有元素

判断栈满,查看栈顶指针是否达到最大值

/*=====================================
 函数功能:判断栈是否为空
 函数输入:顺序栈地址
 函数输出:1——栈空;0——栈非空
 ====================================*/
int StackEmpty_SqStack(SeqStack *s)
{
    return(s->top == -1);                   //此处简化运行代码,不需要进行 if 判断
}

/*=====================================
 函数功能:判断栈是否满
 函数输入:顺序栈地址
 函数输出:1——栈满;0——栈非满
 ====================================*/

int StackCompletely(SeqStack *s)
{
    return(s->top == Stack_Size - 1);
}

4.压栈

将数值1、2、3依次压入栈中,示意图如下所示。数字2进栈前,栈顶指针Top指向栈顶元素1所在的位置,要将2入栈,先将栈顶指针Top加1,指向1所在的上一个位置,再把2放入此单元中。

栈的知识点总结(顺序栈和链栈)——应用:数制转换_第2张图片

/*=====================================
 函数功能:压栈
 函数输入:顺序栈地址,压栈数据
 函数输出:0——栈溢出,1——操作正常
 ====================================*/
int Pushu_SqStack(SeqStack *s, int n)        //修改栈内数据,此处必选传址或引用
{
    if(StackCompletely(s))                   //判断栈满
        return false;
    else
    {   s->top++;
        s->data[s->top] = n;
    }
    return true;
}

5.弹栈

顺序栈出栈操作后不需要删除原来的栈顶元素值。因为栈顶元素的位置是通过栈顶指针标示的,不是靠判断栈中的元素值是否存在来确定栈顶的位置。同时也不会对下一次进栈操作产生影响,因为进栈操作是“写操作”,即对原来的单元空间进行覆盖。

栈的知识点总结(顺序栈和链栈)——应用:数制转换_第3张图片

/*=====================================
 函数功能:出栈
 函数输入:顺序栈地址,(弹出数据)
 函数输出:0——栈空,1——操作正常
 注意:弹出数据可以根据程序员选择是否
       需要保存,如不需要删除即可。
 ====================================*/
int Pop_SqStack(SeqStack *s, int *e)
{
    if(StackEmpty_SqStack(s))
        return false;
    else
    {
        *e = s->data[s->top];
        s->top--;
    }
    return true;
}

6.取栈顶元素

和出栈操作类似,只是指针不发生变化。

/*=====================================
 函数功能:取栈顶元素
 函数输入:顺序栈地址,栈顶数据
 函数输出:0——栈空,1——操作正常
 ====================================*/
int Get_SqStack(SeqStack *s, int *e)
{
    if(StackEmpty_SqStack(s))
        return false;
    else
    {
        *e = s->data[s->top];
    }
    return true;
}

7.顺序栈进行数制转换,实现10进制转8进制

#include 
#include 

/*=====================================
 函数功能:数制转换
 转换公式:N = (n / d) * d + n % d
n      n / d       n % d
1348     168         4   ——8进制最低位
168      21          0   ——8进制第二位
21       2           5   ——8进制第三位
2        0           2   ——8进制第四位
 函数输入:顺序栈地址,转换前数据
 函数输出:转换后数据
// ====================================*/
void conversion_S(SeqStack *S, int n)
{
    int e;
    while(n)
    {
        Pushu_SqStack(S, n % 8);
        n = n / 8;
    }
    while(!StackEmpty_SqStack(S))
    {
        Pop_SqStack(S, &e);
        printf("%d", e);
    }
}

int main(int argc, const char * argv[])
{
    SeqStack s;
    initialize_SqStack(&s);
    conversion_S(&s, 1348);
    std::cout<

 

三、链栈

顺序栈存在栈满以后就不能在进栈的问题,这是因为用了定长的数组存储栈的元素。解决的方法可以是使用链式存储结构,让栈空间可以动态扩充。

栈的链式存储结构成为链栈,它是运算受限的单链表,其插入和删除操作仅限制在表头位置上进行。由于只能在链表头部进行操作,故链栈没有必要像链表那样附加头结点。栈顶指针就是链表的头指针。

1.链栈数据结构定义

/*=============================================
 函数功能:链栈结构体定义
 函数输入:无
 函数输出:无
 ============================================*/
typedef struct CLinkStack
{
    int data;
    CLinkStack *next;       //链指针
}LinkStack;
LinkStack *top;             //链顶指针

2.初始化

栈底指针不做实际用途,仅用作判断栈空,不存储数据。

/*=============================================
 函数功能:链栈的初始化(栈顶指针不存储数据)
 函数输入:链栈指针
 函数输出:栈顶指针
 ============================================*/
LinkStack *InitLStack(LinkStack *s)
{
    s = new LinkStack;                               //在自由存储区中分配内存
    //s = (LinkStack*)malloc(sizeof(LinkStack));     //在堆中分配内存,两种方法均可
    s->next = NULL;
    top = s;
    return top;
}

3.判断栈空

/*=============================================
 函数功能:链栈是否为空
 函数输入:链栈头指针
 函数输出:1——链栈为空;0——链栈非空
 ============================================*/
int LinkStackEmpty(LinkStack *top)
{
    return (top->next == NULL);
}

4.压栈

链栈栈底为链表的表尾,栈顶为链表的表头

栈的知识点总结(顺序栈和链栈)——应用:数制转换_第4张图片

/*=============================================
 函数功能:链栈的压栈
 函数输入:(栈顶指针),压栈元素
 函数输出:栈顶指针
 是否需要返回栈顶指针:传址调用是在同地址中的内容传递,
 若子函数中修改了传递的地址,则此被修改的地址是无法
 通过“传址”传送的。此种情形和 top 的指向未发生变化
 ,但是top 指向单元的内容发生变化有所区别。
 ============================================*/
LinkStack *PushLStack(LinkStack *top, int n)
{
    LinkStack *s = new LinkStack;               //在自由存储区分配内存
    s->data = n;
    s->next = top;
    top = s;
    return top;                                 //top 地址发生改变
}

5.弹栈

/*=============================================
 函数功能:链栈的弹栈
 函数输入:(栈顶指针),压栈元素
 函数输出:栈顶指针
 ============================================*/
LinkStack *PopLStack(LinkStack *top, int *datap)
{
    if(top != NULL)
    {
        *datap = top->data;
        LinkStack *s;
        s = top;
        top = top->next;
        delete s;
    }
    return top;
}

6.链栈进行数制转换,实现10进制转8进制

//
//  main.cpp
//  栈的应用数制转换
//
//  Created by 一丁 on 2019/4/17.
//  Copyright © 2019年 LGD. All rights reserved.
//
#include 
#include 
//#include "LinkStack.h"
//#include "Stack.h"

/*=====================================
 函数功能:数制转换
 转换公式:N = (n / d) * d + n % d
n      n / d       n % d
1348     168         4   ——8进制最低位
168      21          0   ——8进制第二位
21       2           5   ——8进制第三位
2        0           2   ——8进制第四位
 函数输入:顺序栈地址,转换前数据
 函数输出:转换后数据
// ====================================*/


void conversion_L(LinkStack *top, int n)
{
    int e;
    while(n)
    {
        top = PushLStack(top, n % 8);       //要把返回值地址赋值给 top,因为在压栈后 top 地址发生了变化
        n = n / 8;
    }
    while(!LinkStackEmpty(top))
    {
        top = PopLStack(top, &e);
        printf("%d", e);
    }
}

int main(int argc, const char * argv[])
{
    LinkStack l;
    InitLStack(&l);
    conversion_L(&l, 1348);
    return 0;
}

 

你可能感兴趣的:(#,C++容器详解)