Loading


返回 我的技术栈(Technology Stack)



栈(stack)是限定仅在表尾进行插入和删除操作的线性表。

允许插入和删除的一段称为栈顶(top),另一端称为栈底(bottom),不含任何数据元素的栈称为空栈
栈又称为后进先出(Last In First Out)的线性表,简称LIFO结构

栈的插入操作,叫作进栈,也称为压栈、入栈
栈的删除操作,叫作出栈,也有的叫作弹栈


栈的顺序存储结构

image

#include <stdlib.h>
#define MAXSIZE 5		/*存储空间初始分配量*/
#define OK 1		
#define ERROR 0
#define TRUE 1
#define FALSE 0

typedef int SElemType;
typedef int Status;   /*Status是函数的类型,其值是函数结果状态代码,如ok等*/
typedef int ElemType;    /*ElemType 类型*/
/*
*栈的 【顺序存储结构】
*/
typedef struct
{
	SElemType data[MAXSIZE];
	int top; /*用于指向栈顶的指针*/
}SqStack;

C语言实现

初始化操作

/*
*【0】初始化栈 操作
*/
void iniStack(SqStack* s)
{
	s->top=-1;  //只需要将栈顶指针初始化为-1
}

进栈操作

/*
*【1】入栈操作
*操作结果:插入元素e为新的栈顶元素
*/
Status Push(SqStack* s, SElemType e)
{
	if (s->top == MAXSIZE - 1)  /*栈满*/
	{
		return ERROR;
	}

	s->top++;  /*栈顶指针加1*/
	s->data[s->top] = e;   /*将新插入元素赋值给栈顶空间*/
	// s->data[s->top++] = e ; 一条语句实现入栈

	return OK;
}

出栈操作

/*
*【2】出栈操作
*操作结果:若栈不空,则删除 s 的栈顶,用 e 返回其值,并返回OK;否则返回ERROR
*/
Status Pop(SqStack* s, SElemType* e)
{
	if (s->top == -1)  /*栈空*/
	{
		return ERROR;
	}

	*e = s->data[s->top];   /*将要删除的栈顶元素赋值给e*/
	s->top--;  /*栈顶指针减1*/
	
	//*e = s->data[s->top--] ; 一条语句实现出栈

	return OK;
}

两栈共享空间

image

#include <stdlib.h>
#define MAXSIZE 5		/*存储空间初始分配量*/
#define OK 1		
#define ERROR 0
#define TRUE 1
#define FALSE 0

typedef int SElemType;
typedef int Status;   /*Status是函数的类型,其值是函数结果状态代码,如ok等*/
typedef int ElemType;    /*ElemType 类型*/

/*
*两栈共享结构
*/
typedef struct
{
	SElemType data[MAXSIZE];
	int top1; /*栈1栈顶指针*/
	int top2; /*栈2栈顶指针*/
}SqDoubleStack;

C语言实现

入栈操作

/*
*【1】入栈操作
*操作结果:插入元素e为新的栈顶元素
* 【除了要插入元素值之外,还需要一个判断是栈1还是栈2的栈好参数stackNumber】
*/
Status Push(SqDoubleStack* s, SElemType e, int stackNumber)
{
	if (s->top1 + 1 == s->top2)  /*栈满,不能再push新元素了*/
	{
		return ERROR;
	}

	if (stackNumber == 1)  /*栈1有元素进栈*/
	{
		s->data[++s->top1] = e;  /*栈1先 top1+1 后给数组元素赋值*/
	}
	else if (stackNumber == 2)  /*栈2有元素进栈*/
	{
		s->data[--s->top2] = e; /*栈2先 top2-1 后给数组元素赋值*/
	}

	return OK;
}

出栈操作

/*
*【2】出栈操作
*操作结果:若栈不空,则删除 s 的栈顶,用 e 返回其值,并返回OK;否则返回ERROR
*/
Status Pop(SqDoubleStack* s, SElemType* e, int stackNumber)
{
	if (stackNumber == 1)
	{
		if (s->top1 == -1)
			return ERROR;    /*说明栈1 已经是空栈,溢出*/

		*e = s->data[s->top1--];  /*将 栈1 栈顶的元素出栈*/
	}
	else if (stackNumber == 2)
	{
		if (s->top2 == MAXSIZE)
			return ERROR;    /*说明栈2 已经是空栈,溢出*/

		*e = s->data[s->top2++];    /*将 栈2 栈顶的元素出栈*/
	}

	return OK;
}

栈的链式存储结构

对于链栈来说,基本不存在满栈的情况,除非内存已经没有可以使用的空间,
如果真的发生。那此时的计算机操作系统已经面临死机崩溃的情况,而不是这个链表是否溢出的问题。
image

#include <stdlib.h>
#define MAXSIZE 5		/*存储空间初始分配量*/
#define OK 1		
#define ERROR 0
#define TRUE 1
#define FALSE 0

typedef int SElemType;
typedef int Status;   /*Status是函数的类型,其值是函数结果状态代码,如ok等*/
typedef int ElemType;    /*ElemType 类型*/

/*
*链栈的结构代码
*/
typedef struct StackNode
{
	SElemType data;
	struct StackNode* next;
}StackNode, * LinkStackPtr;

typedef struct LinkStack
{
	LinkStackPtr top;
	int count;
}LinkStack;

C语言实现

入栈操作

image

/*
*【1】入栈操作
*操作结果:插入元素e为新的栈顶元素
*/
Status Push(LinkStack *S, SElemType e)
{
	LinkStackPtr s = (LinkStackPtr)malloc(sizeof(StackNode));

	s->data = e;
	s->next = S->top;  /*把当前的栈顶元素赋值给新结点的直接后继,如图中 1 的操作*/

	S->top = s;  /*把新的结点s 赋值给栈顶指针,如图中 2 的操作*/
	S->count++;

	return OK;
}

出栈操作

image

/*
*【2】出栈操作
*操作结果:若栈不空,则删除 s 的栈顶元素,用 e 返回其值,并返回OK;否则返回ERROR
*/
Status Pop(LinkStack *S, SElemType *e)
{
	LinkStackPtr p;
	if (StackEmpty(*s)) 
	{
		return ERROR;
	}

	*e = S->top->data;  
	p = S->top;   /*将栈顶结点赋值给p , 如图 3 操作*/
	S->top = S->top->next;  /*使得栈顶指针下移一位,指向后一结点, 如图 4 操作*/

	free(p);  /*释放结点 p */

	S->count--;
	return OK;
}

迭代与递归的区别

迭代:使用的是循环结构不需要反复调用函数和占用额外的内存。
递归:使用的是选择结构,可以使程序的结构更清晰、更简洁、更容易让人理解,从而减少阅读代码时间,但是大量的递归会导致建立函数的副本,会消耗大量的时间和内存。


参考:
[1]大话数据结构/程杰著.——北京:清华大学出版社,2011.6


posted @ 2021-08-10 09:57  言非  阅读(79)  评论(0编辑  收藏  举报