详解数据结构:栈

server/2024/12/22 3:01:58/

一、顺序

顺序的存储方式如下:

从图中可以看出,顺序需要两个指针,base指向底,top指向顶。

typedef struct SqStack {ElemType *base; //底指针ElemType *top; //顶指针}SqStack;

说明:

ElemType是元素类型,需要什么类型就写什么类型。

typedef将结构体等价于类型名Sqstack。

定义好了之后,还要先定义一个最大的分配空间,这和数组一样,需要预先分配空间,因此可以采用宏定义:

#define Maxsize 100;  //预先分配空间,这个数值根据实际需要预估确定

上面的结构体定义采用了动态分配的形式,也可以采用静态分配的形式,使用一个长数组存储数据元素,一个整型下标记录顶元素的位置。静态分配的顺序结构定义如下:

typedef struct SqStack {ElemType data[Maxsize]; //定长数组int top; //顶下标}SqStack;

注意:只能在一端操作,后进先出,是人为规定的,也就是说不允许在中间查找,取值,插入,删除等操作。顺序本身是顺序存储的,有人就想:我偏要从中间取一个元素,这也是可以的,但这样做,这就不是了。

1、顺序的初始化

初始化一个空,动态分配Maxsize大小的空间,用S.top和S.base指向该空间的基地址。

代码实现:

bool InitStack(SqStack &S) //构造一个空S{S.base=new int[Maxsize];//为顺序分配一个最大容量为Maxsize的空间if(!S.base)    //空间分配失败return false;S.top=S.base;  //top初始为base,空return true;}

2、入

前要判断是否满,如果已满,则入失败;否则将元素放入顶,顶指针向上移动一个位置(top++)。

图解:

输入1,入(左图)

接着输入2,入(右图)

代码实现:

bool Push(SqStack &S,int e) // 插入元素e为新的顶元素{if(S.top-S.base==Maxsize) //满return false;*(S.top++)=e; //元素e压入顶,然后顶指针加1,等价于*S.top=e; S.top++;return true;}

3、出

前要先判断是否为空,如果是空的,则出失败;否则将顶元素暂存给一个变量,顶指针向下移动一个位置(top--)。

完美图解:

顶元素所在的位置是S.top-1,因此把该元素取出来,暂存在变量e中,然后S.top指针向下移动一个位置。因此可以先移动一个位置,即--S.top,然后再取出元素。

例:顶元素4出前后的状态

注意:因为顺序删除一个元素时,并没有销毁该空间,所以4其实还在那个位置,只不过下一次再有元素进时,就把他覆盖了。相当于该元素已出,因为的内容时S.base到S.top-1。

代码实现:

bool Pop(SqStack &S,int &e) //删除S的顶元素,暂存在变量e中{if(S.base==S.top) //空return false;e=*(--S.top); //顶指针减1,将顶元素赋给ereturn true;}

4、取顶元素

顶元素和出不同。取顶元素只是把顶元素复制一份,顶指针未移动,内元素个数未变。而出顶指针向下移动一个位置,内不在包含这个元素。

完美图解:

顶元素*(S.top-1)即元素4,取值后S.top指针没有改变,内元素的个数也没有改变。

代码实现:

int GetTop(SqStack S) //返回S的顶元素,顶指针不变{if(S.top!=S.base)  //非空return *(S.top-1); //返回顶元素的值,顶指针不变elsereturn -1;}

二、链

可以顺序存储,也可以用链式存储。

顺序是分配一段连续的空间,需要两个指针:base指向底,top指向顶,而链每个节点的地址都不连续,只需要一个顶指针即可。

的每个节点都包含两个域:数据域和指针域。可以把链看作一个不带头结点的单链表,但只能在头部进行插入、删除、取值等操作,不可以在中间和尾部操作。

的结构体定义如下:

typedef struct Snode{ElemType data; //数据域struct Snode *next; //指针域,指向下一个节点的指针}Snode,*LinkStack;

的节点定义和单链表一样,只不过它只能在顶那一端操作而已。

1、链的初始化

初始化一个空的链是不需要头结点的,因此只需要让顶指针为空即可。

代码实现:

typedef struct Snode{ElemType data; //数据域struct Snode *next; //指针域,指向下一个节点的指针}Snode,*LinkStack;

2.

是将新元素节点压入顶。因为链中第一个节点为顶,因此将新元素节点插入到第一个节点的前面,然后修改顶指针指向新结点即可。有点像堆柴,将新的节点堆在顶之上,新的节点成为新的顶。

完美图解:

(1)生成新结点。入前要创建一个新结点,将元素e存入该结点的数据域。

代码实现:

p=new Snode; //生成新结点,用p指针指向该结点p->data=e; //将e放在新结点数据域

(2)将新元素节点插入到第一个节点的前面,然后修改顶指针指向新结点。

赋值解释:

  • p->next=S; //将新结点的指针域指向S,即将S的地址赋值给新结点的指针域。
  • S=p;    //修改顶指针为p

整体代码实现:

bool Push(LinkStack &S,int e) //在顶插入元素e{LinkStack p;p=new Snode; //生成新结点p->data=e; //将e放在新结点数据域p->next=S; //将新结点的指针域指向S,即将S的地址赋值给新结点的指针域S=p;    //修改顶指针为preturn true;}

3.

就是把顶元素删除,绕过指针指向下一个节点,然后释放该结点空间。

赋值解释:

  • p=S;  //用p保存顶元素地址,以备释放
  • S=S->next;  //修改顶指针,指向下一个结点
  • delete p;  //释放原顶元素的空间

代码实现:

bool Pop(LinkStack &S,int &e) //删除S的顶元素,用e保存其值{LinkStack p;if(S==NULL) //空return false;e=S->data;  //将顶元素赋给ep=S;  //用p保存顶元素地址,以备释放S=S->next;  //修改顶指针,指向下一个结点delete p;  //释放原顶元素的空间return true;}

4.顶元素

顶元素和出不同,取顶元素只是把顶元素赋值一份,顶指针并没有改变。而出是指删除顶元素,顶指针指向了下一个元素。

代码实现:

int GetTop(LinkStack S) //返回S的顶元素,不修改顶指针{if(S!=NULL) //非空return S->data; //返回顶元素的值,顶指针不变elsereturn -1;}

顺序和链的所以基本操作都只需要常数事件,所以在事件效率上难分伯仲。在空间效率方面,顺序需要预先分配固定长度的空间,有可能造成空间浪费或溢出;链每次只分配一个节点,除非没有内存,否则不会出现溢出,但是每个节点需要一个指针域,结构性开销增加。因此,如果元素个数变化较大,可以采用链;反之,可以采用顺序。在实际中,顺序比链应用更广泛。

配套完整代码(顺序):

#include<iostream>
using namespace std;#define Maxsize 100  //预先分配空间,这个数值根据实际需要预估确定;typedef struct SqStack {int *base; //底指针int *top; //顶指针
}SqStack;bool InitStack(SqStack &S) //构造一个空S
{S.base=new int[Maxsize];//为顺序分配一个最大容量为Maxsize的空间if(!S.base)    //空间分配失败return false;S.top=S.base;  //top初始为base,空return true;
}bool Push(SqStack &S,int e) // 插入元素e为新的顶元素
{if(S.top-S.base==Maxsize) //满return false;*(S.top++)=e; //元素e压入顶,然后顶指针加1,等价于*S.top=e; S.top++;return true;
}bool Pop(SqStack &S,int &e) //删除S的顶元素,暂存在变量e中
{if(S.base==S.top) //空return false;e=*(--S.top); //顶指针减1,将顶元素赋给ereturn true;
}int GetTop(SqStack S) //返回S的顶元素,顶指针不变
{if(S.top!=S.base)  //非空return *(S.top-1); //返回顶元素的值,顶指针不变elsereturn -1;
}int main()
{int n,x;SqStack S;InitStack(S);//初始化一个顺序Scout<<"请输入元素个数n:"<<endl;cin>>n;cout<<"请依次输入n个元素,依次入:"<<endl;while(n--){cin>>x; //输入元素Push(S,x);}cout<<"元素依次出:"<<endl;while(S.top!=S.base)//如果不空,则依次出{cout<<GetTop(S)<<"\t";//输出顶元素Pop(S,x);   //顶元素出}return 0;
}

配套完整源代码(链):

#include<iostream>
using namespace std;typedef struct Snode{int data; //数据域struct Snode *next; //指针域
}Snode,*LinkStack;bool InitStack(LinkStack &S)//构造一个空S
{S=NULL;return true;
}bool Push(LinkStack &S,int e) //在顶插入元素e
{LinkStack p;p=new Snode; //生成新结点p->data=e; //将e放在新结点数据域p->next=S; //将新结点的指针域指向S,即将S的地址赋值给新结点的指针域S=p;    //修改顶指针为preturn true;
}bool Pop(LinkStack &S,int &e) //删除S的顶元素,用e保存其值
{LinkStack p;if(S==NULL) //空return false;e=S->data;  //将顶元素赋给ep=S;  //用p保存顶元素地址,以备释放S=S->next;  //修改顶指针,指向下一个结点delete p;  //释放原顶元素的空间return true;
}int GetTop(LinkStack S) //返回S的顶元素,不修改顶指针
{if(S!=NULL) //非空return S->data; //返回顶元素的值,顶指针不变elsereturn -1;
}int main()
{int n,x;LinkStack S;InitStack(S);//初始化一个顺序Scout<<"请输入元素个数n:"<<endl;cin>>n;cout<<"请依次输入n个元素,依次入:"<<endl;while(n--){cin>>x; //输入元素Push(S,x);}cout<<"元素依次出:"<<endl;while(S!=NULL)//如果不空,则依次出{cout<<GetTop(S)<<"\t";//输出顶元素Pop(S,x);   //顶元素出}return 0;
}


http://www.ppmy.cn/server/13114.html

相关文章

Maven POM元素解析(二)

一、parent <parent>元素包含定位此项目将从中继承的父项目所需的信息。注意&#xff1a;此元素的子元素不是插值的&#xff0c;必须作为文字值给定。 ElementTypeDescriptiongroupIdString要从中继承的父项目的组id。artifactIdString要从中继承的父项目的项目id。ver…

易点易动设备管理系统:赋能制造企业的数字化转型

对于制造企业来说,设备管理是一项至关重要的业务环节。生产设备是制造企业的核心资产,直接关系到整个生产系统的稳定性和生产效率。然而,在实际的生产管理中,很多制造企业仍然存在设备管理方面的诸多痛点和挑战。如何有效管理好设备资产,确保设备的稳定运行和最佳使用效率,一直…

Rust编程入门教程

一、Rust简介 Rust是一种面向对象的系统编程语言&#xff0c;其设计旨在提供内存安全而无需使用垃圾收集机制。Rust拥有高效的编译速度和运行时性能&#xff0c;并且具有强大的并发支持&#xff0c;是构建高性能、可靠且安全软件的理想选择。 二、安装Rust 首先&#xff0c;…

3DE DELMIA Role: PSFEM - Structure Fabrication Engineer for Marine

Discipline: Process Engineering Role: PSFEM - Structure Fabrication Engineer for Marine 通过结构详细设计生成的基于规则的自动化工作准备&#xff0c;用于管理用于生产的制造可交付成果 所有结构设计零件的基于规则的工作准备和对应的生产可交付成果(工程图、机器数据&…

【软件测试】采用等价类划分法设计测试用例

例题1 请采用等价类划分法设计测试用例。 考虑软件 app, 它有两个输入变量 , 分别是 name 和 age, 其中 ,name 是至多包含 20 个字母字符的非空字符串 ,age 是整数型变量 ,0 ≤ age ≤ 120 。当输入给 name 的字符串的长度超过 20时 ,name 取前 20 个字符作为 name 的值 ; 如果…

2024第六届亚洲机器学习与计算大会(ACMLC 2024)即将召开!

2024第六届亚洲机器学习与计算大会&#xff08;ACMLC 2024&#xff09;将于2024年7月26-28日在泰国曼谷举行。从智能语音识别、图像识别到自动驾驶、智能医疗&#xff0c;机器学习与计算技术的应用已经渗透到各个领域&#xff0c;为社会进步和经济发展注入了强大的动力。探秘机…

Redis可视化工具RedisInsight

下载地址&#xff1a;RedisInsight - The Best Redis GUIRedisInsight provides an intuitive and efficient graphical interface for Redis, allowing you to interact with your databases and manage your data.https://redis.com/redis-enterprise/redis-insight/#insight…

【MySQL】表的增删改查

目录 前言&#xff1a; 新增&#xff08;Create&#xff09;&#xff1a; 查询&#xff08;Retrieve&#xff09;&#xff1a; 别名&#xff1a; 去重&#xff1a;DISTINCT 排序&#xff1a;ORDER BY &#xff1a; 条件查询&#xff1a;WHERE &#xff1a; 分页查询&am…