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;
}
输出: