嵌入式0基础开始学习 Ⅱ 数据结构(3)栈

1.1 栈的概念

栈是一种思想 ( 应用方法 )
本质上来说,栈是操作受限的线性表
栈是一种 后进先出 Last In First Out, LIFO )的线性表
栈值允许在表的一段进行插入和删除
允许 进行插入和删除的这一端称之为 ----- 栈顶( Top , 另外一端称之为栈底
满栈:是指 top 永远指向的是最后压入栈的数据的位置,入栈时 top 先操作,再进行数据入栈
空栈:是指 top 永远指向的是下一个要入栈的位置,入栈时先进行数据的入栈,再对 top 进行操作
增栈 : 堆栈由低地址向高地址生长
减栈:堆栈由高地址向低地址生长
根据以上概念可以有四种组合:
递增满栈,递增空栈,递减满栈,递减空栈
共享栈 : 两个栈共用同一块内存区域,一个栈由低地址向高地址生长,另一个栈由高地址向低地址
生长
上溢 : 栈已经满了,无法进行入栈操作了
下溢 : 栈已经空了,无法进行出栈操作了

1.2 栈的存储结构

1.2.1 顺序结构
栈的顺序结构存储,也称之为顺序栈
顺序栈是利用一组连续的存储单元来存放栈的元素
同时,需要一个 top" 指针 "( 数组下标 ) ,来表示栈元素的位置
顺序栈的空间是有限的,当一个元素入栈时,一般需要判断栈是否满了
如果栈满,则元素不能入栈
假设数据元素类型是 int, 则顺序栈的一般定义如下 :
#define MAXSIZE 10
typedef struct SeqStack
{
int data[MAXSIZE]; //地址连续的存储单元
int top; //栈顶“指针”
}SeqStack;
栈的基本操作 :
创建一个数据元素为空的栈 stack_init()
入栈 push()
出栈 pop()
读取栈顶元素 get_top()
判断栈空 empty()
.........
1.2.2 链式结构
用单链表来实现栈这种思想,也称之为链式栈
本质上来说 :
链式栈就是一个只能在一端添加和删除结点的单链表

顺序栈代码:

SeqStack.c

#include "SeqStack.h"


/*
	功能: 初始化一个栈,此时栈中无数据
	返回值:
		返回栈的地址
*/
SeqStack* seqstack_init()
{
	SeqStack* s = malloc(sizeof(SeqStack));
	s->top = -1;		//top置为-1,表示栈目前是空的

	return s;
}

/*
	功能: 入栈
	参数:
		stack: 栈的地址
		value: 需要入栈的数据
*/
void push_stack(SeqStack* stack, ElemType value)
{
	//判断栈是否已满
	if(stack->top == MAXSIZE-1)
	{
		printf("栈已满,无法进行入栈操作\n");
		return ;
	}

	stack->top++;	//栈顶“指针”指向需要入栈的位置
	//data[top]
	stack->data[stack->top] = value; //数据入栈
}

/*
	功能: 出栈
	参数:
		stack: 栈的地址
	返回值:
		成功返回出栈的数据
		失败返回0
*/
ElemType pop_stack(SeqStack* stack)
{
	//判断栈是否为空
	if(stack_empty(stack))
	{
		printf("栈已经为空,无法进行出栈操作\n");
		return 0;
	}

	ElemType temp = stack->data[stack->top]; //栈顶元素的数据
	stack->data[stack->top] = 0;
	stack->top--;

	return temp;
}




/*
	功能: 获取栈顶元素的数据
	参数:
		栈的地址
	返回值:
		成功返回获取到的栈顶元素的数据
		失败返回0
*/
ElemType get_top(SeqStack* stack)
{
	//判断栈是否为空
	if(stack_empty(stack))
	{
		printf("栈已经为空,无法获取栈顶元素\n");
		return 0;
	}

	//data[top]
	return stack->data[stack->top];
}


/*
	功能: 判断栈是否为空
	参数:
		stack: 栈的地址
	返回值:
		为空则返回  true
		不为空则返回false
*/
bool stack_empty(SeqStack* stack)
{
	if(stack->top == -1)
		return true;

	return false;
}

/*
	功能: 清空一个栈
	参数:
		stack: 栈的地址
*/
void clear_stack(SeqStack* stack)
{
	if(stack_empty(stack))
		printf("栈已经为空,不需要再清空\n");
	else 
		stack->top = -1;
}


/*
	功能: 销毁一个栈
	参数:
		stack: 栈的地址
*/
SeqStack* destroy_stack(SeqStack* stack)
{
	while(1)
	{
		if(stack->top == -1) //栈已清空
			break;

		stack->data[stack->top] = 0;
		stack->top--;
	}

	free(stack);

	stack = NULL; //避免产生悬挂指针

	return stack;
}











SeqStack.h

#ifndef		__SEQSTACK__
#define		__SEQSTACK__


#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#define MAXSIZE 10

typedef int ElemType;

typedef struct SeqStack
{
	ElemType data[MAXSIZE];		//地址连续的存储单元
	int	top;					//栈顶"指针"
}SeqStack;


SeqStack* seqstack_init();
void push_stack(SeqStack* stack, ElemType value);
ElemType get_top(SeqStack* stack);
ElemType pop_stack(SeqStack* stack);
bool stack_empty(SeqStack* stack);
void clear_stack(SeqStack* stack);
SeqStack* destroy_stack(SeqStack* stack);











#endif 



main.c

#include "SeqStack.h"

int main()
{
	//初始化栈
	SeqStack* stack = seqstack_init();
	
	//入栈
	push_stack(stack, 100);
	push_stack(stack, 200);
	push_stack(stack, 300);

	//清空栈
	//clear_stack(stack);

	//销毁栈
	//stack = destroy_stack(stack);

	//出栈
	ElemType value = pop_stack(stack);
	if(value != 0)
		printf("value = %d\n", value);

	//获取栈顶元素的数据
	ElemType top_data = get_top(stack);
	if(top_data != 0)
		printf("top_data = %d\n", top_data);

	return 0;
}













链式栈代码:

Stack.c

#include "Stack.h"


/*
	功能: 初始化一个结点,并把数据写入到结点中
	参数:
		var: 结点的数据
	返回值:
		结点的地址
*/
stack_node*  node_init(ElemType var)
{
	//先申请一个结点那么大的存储空间
	stack_node* pnew = malloc(sizeof(stack_node));
	//往结点中写入数据
	pnew->data = var;
	pnew->next = NULL;

	return pnew;
}

/*
	功能: 初始化一个头结点
	返回值:
		返回头结点的地址
*/
Stack* stack_init()
{
	//先申请一个头结点那么大的存储空间
	Stack* stack = malloc(sizeof(Stack));
	stack->low = NULL;
	stack->top = NULL;
	stack->num = 0;

	return stack;
}

/*
	功能: 入栈
	参数:
		stack: 栈的地址
		value: 需要入栈的数据
*/
void push_stack(Stack* stack, ElemType value)
{
	//初始化一个新的结点
	stack_node* new_node = node_init(value);

	//从无到有
	if(stack->low == NULL)
	{
		stack->low = new_node;
		stack->top = new_node;
	}
	else //从少到多
	{
		stack->top->next = new_node;
		stack->top = new_node; //栈顶指向最后入栈的元素
	}

	stack->num++;	//栈中元素个数加一
}


/*
	功能: 出栈
	参数:
		栈的地址
	返回值:
		成功返回栈顶元素的值
		失败返回0
*/
ElemType pop_stack(Stack* stack)
{
	if(stack->num == 0)
	{
		printf("栈已经为空,无法进行出栈操作\n");
		return 0;
	}

	stack->num--;

	ElemType value; //用来保存出栈的元素的数据

	//栈中只有一个元素
	if(stack->low->next == NULL)
	{
		value = stack->top->data; //存储出栈的元素的数据
		stack_node* temp = stack->top;
		stack->low = NULL;
		stack->top = NULL;
		free(temp);
		return value;
	}
	else //栈中有多个元素,释放栈顶元素
	{
		stack_node* p = stack->low;	//从栈低往栈顶去找
		stack_node* pre = NULL;		//保存栈顶的前一个元素的地址

		while(1)
		{
			if(p == stack->top) //找到栈顶的位置
			{
				value = stack->top->data; //存储出栈的元素的数据
				stack->top = pre;	//确定新的栈顶
				stack->top->next = NULL; //把需要删除的结点与原来栈之间的连续断开
				free(p);
				return value;
			}

			pre = p; //先保存p现在指向的结点的地址
			p = p->next;	//p去遍历栈
		}
	}


}

/*
	功能: 获取栈顶元素的数据
	参数:
		stack: 栈的地址
	返回值:
		成功返回栈顶元素的值
		失败返回0
*/
ElemType get_top(Stack* stack)
{
	if(stack->num == 0)
	{
		printf("栈已经为空,无法获取栈顶元素的数据\n");
		return 0;
	}
	else 
		return stack->top->data;
}


/*
	功能: 销毁一个栈
	参数:
		栈的地址
	返回值:
		NULL
*/
Stack* destory_stack(Stack* stack)
{
	stack_node* p = stack->low;	//从栈底往栈顶进行遍历
	stack_node* q = NULL;		//用来保存需要释放的元素指向的下一个元素的地址

	while(p != NULL)
	{
		q = p->next;
		p->next = NULL;
		free(p);
		p = q;
	}

	stack->low = NULL;
	stack->top = NULL;
	stack->num = 0;

	free(stack);
	stack = NULL;

	return stack;
}




Stack.h

#ifndef		__STACK_H__
#define		__STACK_H__


#include <stdio.h>
#include <stdlib.h>

typedef  int ElemType; //方便存储的数据的类型做修改

//typedef: 给已有的数据类型起一个别名
//在这里是给struct Node起了一个短一点的名字node
typedef struct Stack_Node
{
	ElemType data;			//数据域
	struct Stack_Node* next;  //指针域
}stack_node; 

//定义头结点的类型,用于存储链表的一些属性信息
typedef struct Stack
{
	stack_node* top;	//保存栈顶的地址
	stack_node* low;	//保存栈底的地址
	int num;			//记录栈中元素的数量
}Stack;


stack_node*  node_init(ElemType var);
Stack* stack_init();
void push_stack(Stack* stack, ElemType value);
ElemType pop_stack(Stack* stack);
ElemType get_top(Stack* stack);
Stack* destory_stack(Stack* stack);



#endif



main.c

#include "Stack.h" 

int main()
{
	Stack* stack = stack_init();

	push_stack(stack, 100);
	push_stack(stack, 200);
	push_stack(stack, 300);

	ElemType top_data = get_top(stack);
	if(top_data != 0)
		printf("top_data = %d\n", top_data);

	pop_stack(stack);
	top_data = get_top(stack);
	if(top_data != 0)
		printf("top_data = %d\n", top_data);

	//stack = destory_stack(stack);
	//top_data = get_top(stack);

	return 0;
}




  • 14
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值