栈及栈的链式存储结构(栈链)

栈:线性结构,后进先出。栈(Stack)是一种特殊的线性表(顺序表,链表)只在表尾进行删除和插入操作。

注意:对于栈来说,表尾称为栈的栈顶(top),表头称为栈底(bottom)。

栈也是线性结构的一种特例。与队列不同,他只有一个口,只能从这里读或者写数据,这个口称为栈顶(top)。栈是一种先进后出的数据结构。先进来的元素会放入栈底,而后进来的元素被放在它的上面,最后进来的元素的上面的位置,称为栈顶。

栈所提供的操作比一般的线性表要少很多,只提供:初始化、销毁、判断是否为空、求栈的长度、清空栈、将数据压入栈、将数据弹出栈、获得栈顶元素这几种操作。其中将数据压入栈、将数据弹出栈、获得栈顶元素是最重要的。有人可能觉得,将栈顶元素弹出与获得栈顶元素是不是有点重复,其实它们主要的目的在于,很多时候你只想知道当前栈顶的元素是谁,而并不想将它弹出。这样做可以简单一点。

了解了栈的基本结构和操作以后,自然而然的想到用数组来实现栈:因为前面的元素并不发生变化,只能在最后面入栈或者出栈。

因为栈的本质是一个线性表,线性表有两种存储形式,那么栈也有分为栈的顺序存储结构和栈的链式存储结构。

最开始栈中不含有任何数据,叫做空栈,此时栈顶就是栈底。然后数据从栈顶进入,栈顶栈底分离,整个栈的当前容量变大。数据出栈时从栈顶弹出,栈顶下移,整个栈的当前容量变小。

栈顶——地址较高;

栈底——地址较低。

定义一个顺序存储的栈,包含三个元素:base、top、stackSize。

typedef struct{
ElemType *base;//栈底
ElemType *top;//栈顶
int stackSize;//栈的当前可使用的最大容量
}sqStack;

或者:

typedef int ElemType;
 typedef struct{
ElemType data[MAXSIZE];
int top;	// 用于标注栈顶的位置
int stackSize;
}

其中base是指栈底的指针变量,top是指栈顶的指针变量,stackSize指栈的当前可使用的最大容量。

创建一个栈:

#define STACK_INIT_SIZE 100

initStack(sqStack *s){
s->base = (ElemType *)malloc( STACK_INIT_SIZE * sizeof(ElemType) );
if( !s->base )
exit(0);

s->top = s->base;   // 最开始,栈顶就是栈底
s->stackSize = STACK_INIT_SIZE;
}

入栈操作:

入栈操作又叫压栈操作,就是向栈中存放数据。

入栈操作要在栈顶进行,每次向栈中压入一个数据,top指针就要+1,直到栈满为止。

出栈操作:

出栈操作就是在栈顶取出数据,栈顶指针随之下移的操作。

每当从栈内弹出一个数据,栈的当前容量就-1。

入栈时,先将值压入栈中,再改变指针top,即将top指针加1;

出栈时,先将top指针减去1,然后再将top指针指向的值从栈中取出;

注意:top指针在开始时指向的位置其实就是将要存放数据的位置,因此它指向的区域是空的,想要将数据从栈中取出,需要首先将top指针指向该位置。

Pop(sqStack *s, ElemType *e){
if( s->top == s->base )  // 栈为空
return;
*e = *--(s->top);
}

栈的其它操作:清空、销毁、计算栈的当前容量等。

1、清空:清空一个栈,就是将栈中的元素全部作废,但栈本身物理空间并不发生改变(不是销毁)。

因此我们只要将s->top的内容赋值为s->base即可,这样s->base等于s->top,也就表明这个栈是空的了。

这个原理跟高级格式化只是但单纯地清空文件列表而没有覆盖硬盘的原理是一样的。

ClearStack(sqStack*s){
s->top= s->base;
}

2、销毁一个栈

销毁一个栈与清空一个栈不同,销毁一个栈是要释放掉该栈所占据的物理内存空间,因此不要把销毁一个栈与清空一个栈这两种操作混淆。

DestroyStack(sqStack *s){
int i, len;
len = s->stackSize;

for( i=0; i < len; i++ )
{
free( s->base );
s->base++;
}

s->base = s->top = NULL;
s->stackSize = 0;
}

3、计算栈的当前容量

计算栈的当前容量也就是计算栈中元素的个数,因此只要返回s.top-s.base即可。

注意,栈的最大容量是指该栈占据内存空间的大小,其值是s.stackSize,它与栈的当前容量不是一个概念哦。

int StackLen(sqStack s){
return(s.top – s.base);
//两个地址相减,返回的是存放在该地址的数据的个数
}

(指针的数学计算:++、--、相减,但是指针不能相加!)

栈的链式存储结构(栈链)

栈因为只是栈顶来做插入和删除操作,所以比较好的方法就是将栈顶放在单链表的头部,栈顶指针和单链表的头指针合二为一。

//栈的链式存储结构(栈链)
teypedef struct StackNode
{
	ElemType data;		// 存放栈的数据
	struct StackNode *next;
} StackNode, *LinkStackPtr;

teypedef struct LinkStack
{
	LinkStackPrt top;	// top指针
	int count;	  // 栈元素计数器
}
//对于栈链的Push操作,假设元素值为e的新结点是s,top为栈顶指针
Status Push(LinkStack *s, ElemType e){
	LinkStackPtr p = (LinkStackPtr) malloc (sizeof(StackNode));
	p->data = e;
	p->next = s->top;
	s->top = p;
	s->count++;
	return OK;
}
//链栈的出栈Pop操作,假设变量p用来存储要删除的栈顶结点,将栈顶指针下移一位,最后释放p即可。
Status Pop(LinkStack *s, ElemType *e){
	LinkStackPtr p;
	if( StackEmpty(*s) )  // 判断是否为空栈
		return ERROR;
 
	*e = s->top->data;
	p = s->top;
	s->top = s->top->next;
	free(p);
	s->count--; 
	return OK;
}
时间: 2024-10-05 03:03:28

栈及栈的链式存储结构(栈链)的相关文章

数据结构_线性表_顺序存储之1顺序栈2共享栈_链式存储之链栈_栈的应用举例

1>//栈是先进后出,后进先出的线性表 简称LIFO线性表 //栈的顺序存储结构成为顺序栈(sequebtial stack). //顺序栈利用一组地址连的存储单元依次存放从栈底到 栈顶的数据元素,通常用一维数组存放栈的元素 //"指针"top并非指针,而是表示栈顶元素的当前位置 //top不是指针型变量而是整形变量,top=0空栈,top=MaxSize 表示满栈,当top>maxsize 表示栈溢出 代码 #include <stdio.h> #includ

数据结构--线性表的链式存储结构

一 线性表的链式存储结构 A.链式存储的定义为了表示每个数据元素与直接后继元素之间的逻辑关系:数据元素除了存储本身的信息外,还需要存储其直接后继的信息图示B链式存储逻辑结构基于链式存储结构的线性表中,每个结点都包含数据域和指针域1.数据域:存储数据元素本身2.指针域:存储相邻结点的地址图示C链表中的基本概念1.头结点--链表中的辅助结点,包含指向第一个数据元素的指针(方便插入和删除)2.数据结点--链表中代表数据元素的结点,表现形式为:(数据元素,地址)3.尾节点--链表中的最后一个数据结点,包

栈的链式存储结构和入栈出栈操作

参考<大话数据结构>P98~99——栈的链式存储结构. 进栈: 出栈: 举个简单的例子: 代码和解释如下(VS2012测试通过): 1 #include <iostream> 2 #include <string> 3 using namespace std; 4 5 typedef string status;//用书上推荐的status返回是否成功,C++中的模板类string比字符数组char[]更方便 6 7 //栈的结点 8 //包含data,和指向下一个结点

栈(链式存储结构)

堆栈:具有一定操作约束的线性表,只能在一端作插入.删除 具有后入先出的特性(Last In First Out) 分顺序存储结构.链式存储结构两种形式 堆栈的顺序存储结构 通常由一个一维数组和一个栈顶元素变量组成 图解如下: 形式一:构建结构体 0.结构初始化 #define MaxSize ### struct StackNode { ElementType Data[MaxSize]; int top; }; 1.建立空栈 struct StackNode* createStack() {

栈的链式存储结构及应用(C、Java代码)

链式存储结构最大的好处就是没有空间的限制,可以通过指针指向将结点像以链的形式把结点链接,我们熟悉的线性表就有链式存储结构. 当然,栈同样有链式存储结构,栈的链式存储结构,简称链栈. 从图片可以看到,和单链表很像,拥有一个头指针top,又称作栈顶指针,所以此时就不再需要单链表里面的头结点了. 对于链栈来说,基本不存在栈满的情况,除非计算机内存已经没有了可使用的空间,如果真的存在,那么计算机系统已经面临着即将死机崩溃的情况,而不是这个链栈是否溢出的问题了. 对于空栈来说,链表的定义是头指针指向NUL

栈的链式存储结构(C语言实现)

1 #include <stdio.h> 2 #include <stdlib.h> 3 4 #define OK 1 5 #define ERR 2 6 #define TRUE 1 7 #define FALSE 0 8 9 typedef int status; //定义函数返回的状态,OK & ERR 10 typedef char datatype; //定义栈中每个元素的数据类型,这里暂定为字符型 11 12 typedef struct LinkStack_a

二叉树的链式存储结构----二叉链表

头文件:head.h #include<string.h> #include<ctype.h> #include<malloc.h> /* malloc()等 */ #include<limits.h> /* INT_MAX等 */ #include<stdio.h> /* EOF(=^Z或F6),NULL */ #include<stdlib.h> /* atoi() */ #include<io.h> /* eof()

队列的顺序存储结构和链式存储结构

队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表(在队尾进行插入操作,在对头进行删除操作). 与栈相反,队列是一种先进先出(First In First Out, FIFO)的线性表. 与栈相同的是,队列也是一种重要的线性结构,实现一个队列同样需要顺序表或链表作为基础. 队列的链式存储结构 队列既可以用链表实现,也可以用顺序表实现.跟栈相反的是,栈一般我们用顺序表来实现,而队列我们常用链表来实现,简称为链队列. typedef struct QNode { ElemT

完全二叉树的链式存储结构的转化 &amp; 非递归中序遍历二叉树

1 /* 2 * 二叉树 3 * 4 * (将完全二叉树的数组形式改为链表形式) 5 * 6 * 1 7 * 2 3 8 * 4 5 6 7 9 * 8 10 * 11 */ 12 #include <iostream> 13 #define MAX 10 14 using namespace std; 15 16 typedef struct btnode{ 17 int data; 18 struct btnode * lchild; 19 struct btnode * rchild;