数据结构(受限线性表-栈)

3受限线性表

 

3.1栈(stack)

3.1.1栈的基本概念

最大特点:先进后出,单端插入和删除 

概念:

首先它是一个线性表,栈元素具有线性关系,即前驱后继的关系,非常特殊的一种线性表。

定义中说是在线性表的表尾进行插入和删除操作,这里表尾是栈顶。

特性:

它的特殊之处在于限制了这个线性表的插入和删除的位置,它始终只是在栈顶进行,这也就使得:

栈底是固定的,最先进栈的只能在栈底。

操作:

栈的插入操作:进栈,压栈。

栈的删除操作:出栈。

操作如图所示:

                             

                        

(图源:大话数据结构) 

3.1.2栈的顺序储存

 栈的顺序存储结构简称顺序栈,它是运算受限制的顺序表。

顺序栈的存储结构是:利用一组地址连续的存储单元,依次存放自栈底到栈顶的数据元素。

同时附设指针top只指向栈顶元素。

下面利用静态数组(一段连续的内存空间)来模拟栈

 重点内容:

结构

//链表节点数据类型
struct Stack_LinkContent
{
    struct Stack_LinkContent * next;
};
//链表数据类型
struct Stack_LinkProperty
{
    struct Stack_LinkContent Content;
    int size;
};
typedef void * Stack_LinkList;//为了更好的让用户理解函数
typedef struct StackTest
{
    Stack_LinkContent node;
    QString name;
    int age;
}ST;

链表详细介绍:https://blog.csdn.net/qq_41605114/article/details/104396149

用户创建的数据结构必须包括Stack_LinkContent

初始化和销毁:

//初始化
Stack_LinkList Init_SSKL()
{
    Stack_LinkProperty * MySL = (Stack_LinkProperty *)malloc(sizeof(Stack_LinkProperty));
    if(MySL == nullptr)
        return nullptr;
    MySL->size = 0;
    MySL->Content.next = nullptr;
    return MySL;
}
//销毁栈
void Destroy_SSKL(Stack_LinkList stacklist)
{
    if(nullptr == stacklist)
        return;
    free(stacklist);
    stacklist = nullptr;

}

初始化的时候malloc,销毁的时候也要对应的有free

不用把free强制转换为malloc时候的类型,因为不管在free里面输入什么类型的参数,最后都会变成万能指针(void *)。

编译器的malloc的时候也已经有标记,所以只要把首地址给free就可以的 

压栈和出栈:

因为只能从一段压栈和出栈,栈的数据结构非常的简单

连续存储结构来说,尾部的位置是最好找的,尾部作为栈顶,也就是下标大的一侧作为栈顶,下标小的一侧作为栈底即可。

而对于链表,这类分散式的来说呢,显然头部是最好找的,所以头指针的位置作为栈顶。

链式存储结构来说,链表最容易获得的就是头指针,所以,在头部压栈,在头部出栈,不同于静态数组

入栈和出栈的示意图如下图所示:

压栈(入栈)示意图: 

                  

出栈

                      

 代码如下:

//入栈
void Push_SSK(SSK stack,void * data)
{
    if(nullptr == stack)
        return;
    if(nullptr == data)
        return;
    StaticStack * Mystack = (StaticStack*)stack;
    Mystack->data[Mystack->size] = data;
    ++Mystack->size;
}
//出栈
void Pop_SSK(SSK stack)
{
    if(nullptr == stack)
        return;
    StaticStack * Mystack = (StaticStack*)stack;
    if(Mystack->size == 0)
        return;
    Mystack->data[Mystack->size-1] = nullptr;
    --Mystack->size;
}

从代码中也可以看出。 

完成版本的代码的输出如下: 

.h 

#ifndef STACKANDMATRIX_H
#define STACKANDMATRIX_H

#include <QWidget>
#include<QDebug>
class StackANDMatrix : public QWidget
{
    Q_OBJECT
public:
    explicit StackANDMatrix(QWidget *parent = nullptr);

signals:

public slots:
};

//数组大小
const int MAX = 1024;//C++中比define安全
//顺序栈数据结构
struct StaticStack
{
    void * data[MAX];//存放数据的数组
    int size;//栈中元素的个数
};
typedef struct StackData
{
    int sizeForData;
    QString name;
}SD;
typedef void * SSK;//为了用户更好的理解
//初始化
SSK Init_SSK();
//入栈
void Push_SSK(SSK stack,void * data);
//出栈
void Pop_SSK(SSK stack);
//获得栈顶元素
void * Top_SSK(SSK stack);
//栈的大小
int Size_SSK(SSK stack);
//销毁栈
void Destroy_SSk(SSK stack);
//在尾部插入,不需要移动元素,以数组高下标的位置作为栈顶,0当做栈底
//过程中不需要移动元素
#endif // STACKANDMATRIX_H

.cpp 

#include "stackandmatrix.h"

StackANDMatrix::StackANDMatrix(QWidget *parent) : QWidget(parent)
{
    qDebug()<<"栈1";
    StaticStack * MyTest = (StaticStack *)Init_SSK();
    SD s1 = {1,"aaa"};
    SD s2 = {2,"bbb"};
    SD s3 = {3,"ccc"};
    SD s4 = {4,"ddd"};
    SD s5 = {5,"eee"};
    qDebug()<<"入栈";
    Push_SSK(MyTest,&s1);
    Push_SSK(MyTest,&s2);
    Push_SSK(MyTest,&s3);
    Push_SSK(MyTest,&s4);
    Push_SSK(MyTest,&s5);

    //栈输出一个删除一个
    qDebug()<<"Size_SSK:"<<Size_SSK(MyTest);

    while(Size_SSK(MyTest)>0)
    {
        SD * SDponiter = (SD * )Top_SSK(MyTest);
        qDebug()<<"SDponiter->sizeForData:"<<SDponiter->sizeForData
               <<"SDponiter->name:"<<SDponiter->name;

        //输出后一定要弹出
        Pop_SSK(MyTest);
    }
    qDebug()<<"Size_SSK:"<<Size_SSK(MyTest);
    qDebug()<<"销毁";
    Destroy_SSk(MyTest);
    MyTest = nullptr;

}
//初始化
SSK Init_SSK()
{
    StaticStack * stack = (StaticStack *)malloc(sizeof(StaticStack));
    if(nullptr == stack)
        return nullptr;
    stack->size = 0;
    memset(stack,0,sizeof(StaticStack));
    return stack;
}
//入栈
void Push_SSK(SSK stack,void * data)
{
    if(nullptr == stack)
        return;
    if(nullptr == data)
        return;
    StaticStack * Mystack = (StaticStack*)stack;
    Mystack->data[Mystack->size] = data;
    ++Mystack->size;
}
//出栈
void Pop_SSK(SSK stack)
{
    if(nullptr == stack)
        return;
    StaticStack * Mystack = (StaticStack*)stack;
    if(Mystack->size == 0)
        return;
    Mystack->data[Mystack->size-1] = nullptr;
    --Mystack->size;
}
//获得栈顶元素
void * Top_SSK(SSK stack)
{
    if(nullptr == stack)
        return nullptr;
    StaticStack * Mystack = (StaticStack*)stack;
    if(Mystack->size==0)
        return nullptr;
    return Mystack->data[Mystack->size-1];

}
//栈的大小
int Size_SSK(SSK stack)
{
    if(nullptr == stack)
        return 0;
    StaticStack * Mystack = (StaticStack*)stack;
    return Mystack->size;

}
//销毁栈
void Destroy_SSk(SSK stack)
{
    if(nullptr == stack)
        return;
    free(stack);
}

 

整个程序比较简单,注意以下几点:

连续储存空间,在尾部插入,不需要移动元素,以数组高下标的位置作为栈顶,0当做栈底,过程中不需要移动元素

 

3.1.3栈的链式存储

栈的形式简单,之前也赘述过栈的结构,此处就不多赘述。 

.h

#ifndef STACKLIST_H
#define STACKLIST_H

#include <QWidget>
#include<QDebug>
class StackList : public QWidget
{
    Q_OBJECT
public:
    explicit StackList(QWidget *parent = nullptr);

signals:

public slots:
};
//显然,对于链表来说,头指针是一直知道的,所以,从头部入栈,从头部出栈
//链表节点数据类型
struct Stack_LinkContent
{
    struct Stack_LinkContent * next;
};
//链表数据类型
struct Stack_LinkProperty
{
    struct Stack_LinkContent Content;
    int size;
};
typedef void * Stack_LinkList;//为了更好的让用户理解函数
typedef struct StackTest
{
    Stack_LinkContent node;
    QString name;
    int age;
}ST;
//初始化
Stack_LinkList Init_SSKL();
//入栈
void Push_SSKL(Stack_LinkList stacklist,void * data);
//出栈
void Pop_SSKL(Stack_LinkList stacklist);
//获得栈顶元素
void * Top_SSKL(Stack_LinkList stacklist);
//栈的大小
int Size_SSKL(Stack_LinkList stacklist);
//销毁栈
void Destroy_SSKL(Stack_LinkList stacklist);
#endif // STACKLIST_H

.cpp 

#include "stacklist.h"

StackList::StackList(QWidget *parent) : QWidget(parent)
{
    qDebug()<<"链表栈";
    Stack_LinkProperty * list = (Stack_LinkProperty*)Init_SSKL();


    ST t1 = {nullptr,"1",10};
    ST t2 = {nullptr,"2",20};
    ST t3 = {nullptr,"3",30};
    ST t4 = {nullptr,"4",40};
    ST t5 = {nullptr,"5",50};

    Push_SSKL(list,&t1);
    Push_SSKL(list,&t2);
    Push_SSKL(list,&t3);
    Push_SSKL(list,&t4);
    Push_SSKL(list,&t5);

    //栈输出一个删除一个
    qDebug()<<"Size_SSK:"<<Size_SSKL(list);

    while(Size_SSKL(list)>0)
    {
        ST * STponiter = (ST * )Top_SSKL(list);
        qDebug()<<"STponiter->age:"<<STponiter->age
               <<"STponiter->name:"<<STponiter->name;

        //输出后一定要弹出
        Pop_SSKL(list);
    }
    qDebug()<<"Size_SSK:"<<Size_SSKL(list);
    qDebug()<<"销毁";
    Destroy_SSKL(list);
    list = nullptr;




}
//初始化
Stack_LinkList Init_SSKL()
{
    Stack_LinkProperty * MySL = (Stack_LinkProperty *)malloc(sizeof(Stack_LinkProperty));
    if(MySL == nullptr)
        return nullptr;
    MySL->size = 0;
    MySL->Content.next = nullptr;
    return MySL;
}
//入栈
void Push_SSKL(Stack_LinkList stacklist,void * data)
{
    if(nullptr == stacklist)
        return;
    if(nullptr == data)
        return;
    Stack_LinkProperty * MySL = (Stack_LinkProperty *)stacklist;
    Stack_LinkContent * Mydata = (Stack_LinkContent *)data;

    Mydata->next = MySL->Content.next;
    MySL->Content.next = Mydata;

    ++(MySL->size);

}
//出栈
void Pop_SSKL(Stack_LinkList stacklist)
{
    if(nullptr == stacklist)
        return;
    Stack_LinkProperty * MySL = (Stack_LinkProperty *)stacklist;
    Stack_LinkContent * Mydata = (Stack_LinkContent *)(MySL->Content.next);

    if(MySL->size == 0)
        return;
    MySL->Content.next = Mydata->next;
    --(MySL->size);
}
//获得栈顶元素
void * Top_SSKL(Stack_LinkList stacklist)
{
    if(nullptr == stacklist)
        return nullptr;
    Stack_LinkProperty * MySL = (Stack_LinkProperty *)stacklist;

    if(MySL->size == 0)
        return nullptr;
    return MySL->Content.next;

}
//栈的大小
int Size_SSKL(Stack_LinkList stacklist)
{
    if(nullptr == stacklist)
        return 0;
    Stack_LinkProperty * MySL = (Stack_LinkProperty *)stacklist;

    if(MySL->size == 0)
        return 0 ;
    return MySL->size;

}
//销毁栈
void Destroy_SSKL(Stack_LinkList stacklist)
{
    if(nullptr == stacklist)
        return;
    free(stacklist);
    stacklist = nullptr;

}

输出: 

 

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值