2022.4.5 栈

69 篇文章 3 订阅
21 篇文章 0 订阅
本文详细介绍了顺序栈的数据结构原理,包括栈的概念、特点和栈顶栈底的定义。此外,还展示了如何通过结构体设计和一系列操作函数来创建和管理栈,如初始化、入栈、出栈、判断空满等。通过实例代码演示了栈的使用和常见操作,适合初学者理解栈的典型应用。
摘要由CSDN通过智能技术生成
  1. 栈的概念
    只能在表尾进行插入(入栈)和删除(出栈)的数据结构,也就是表头和中间不能插入和删除(受到限制的线性表);
    其表尾比较特殊,我们一般把这个表尾叫做栈顶,表头端叫栈底,没有数据节点,则叫空栈。
    特点:后进先出(先进后出)
  2. 栈的表现形式
    在这里插入图片描述
  3. 因为栈只能在表尾进行插入(入栈)和删除(出栈),因此在写可操作函数时,没有头删头插等
  4. 结构体设计
struct Stack
{
    第一个数据成员:ELEM_TYPE *base (指针类型,用来接收malloc从堆里申请的一整块连续的空       间)
    第二个数据成员:int top  (栈顶指针,但不用刻板的认为一定是指针类型)(即就是需要一个变量,既能表示下一个数据的插入位置,又能表示有多少个有效值
    第三个数据成员:int stack_size(存储当前容量的大小)
};

注意:① base称为栈底指针,在顺序栈中,它始终指向栈底的位置, 如果base为
NULL,则表明栈结构不存在
② top为栈顶指针,其初始值指向栈底,即top=base可作为栈空的标记,每当插入
新的栈顶元素时,指针top增1,删除栈顶元素时,指针top减1
5. 子函数想影响父函数,必须取地址加解引用。
6. 代码
stack.h头文件

#pragma once


//顺序栈的结构体设计
#define INIT_SIZE 10
typedef int ELEM_TYPE;

typedef struct stack
{
	ELEM_TYPE* base;//指针,用来接收malloc从堆内申请的一整块内存
	int top;//和书上不一致,书上是指针类型,这块存的是数组下标,所以用int 类型,也可以达到指针的作用
	int stack_size;//变量,存储当前的最大容量
}Stack,*PStack;

//顺序栈可执行函数的声明
//初始化
void Init_stack(struct stack* ps);

//入栈(插入节点)
bool Push(struct stack* ps,ELEM_TYPE val);

//出栈(获取栈顶元素值,并且删除)//用到一个输出参数
bool Pop(PStack ps, ELEM_TYPE *rtval); //ELEM_TYPE *告诉获取的值是多少,PStack ps获取值是否成功

//获取栈顶元素(获取栈顶元素值,但是不删除)
bool Top(PStack ps, ELEM_TYPE* rtval);

//判空
bool Isempty(PStack ps);

//判满
bool Isfull(PStack ps);

//扩容
void Inc(PStack ps);

//获取有效长度
int Get_length(PStack ps);

//清空
void Clear(PStack ps);

//销毁
void Destroy(PStack ps);

//打印
void Show(PStack ps);

stack.cpp头文件

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include"stack.h"


//顺序栈可执行函数的声明
//初始化
void Init_stack(struct stack* ps)
{
	assert(ps != NULL);
	if (ps == NULL)
	{
		return;
	}
	ps->base = (ELEM_TYPE*)malloc(INIT_SIZE * sizeof(struct stack));
	ps->top = 0;//初始状态
	ps->stack_size = INIT_SIZE;
}

//入栈(插入节点)
bool Push(struct stack* ps, ELEM_TYPE val)
{
	assert(ps != NULL);
	if (ps == NULL)
	{
		return false;
	}
	//入栈,需要判满,如果满了,扩容
	if (Isfull(ps))
	{
		Inc(ps);
	}

	//肯定有额外空间入栈
	ps->base[ps->top] = val;
	//记得,插入和删除结束后挪动栈顶指针
	ps->top++;

	return true;

}

//出栈(获取栈顶元素值,并且删除)//用到一个输出参数
bool Pop(PStack ps, ELEM_TYPE* rtval) //ELEM_TYPE *告诉获取的值是多少,PStack ps获取值是否成功
{
	assert(ps != NULL);
	if (ps == NULL)
	{
		return false;
	}
	//出栈,需要判空
	if (Isempty(ps))
	{
		return false;
	}
	ps->top--;

	*rtval = ps->base[ps->top];
	return true;

}

//获取栈顶元素(获取栈顶元素值,但是不删除)
bool Top(PStack ps, ELEM_TYPE* rtval)
{
	assert(ps != NULL);
	if (ps == NULL)
	{
		return false;
	}
	if (Isempty(ps))
	{
		return false;
	}

	*rtval = ps->base[ps->top - 1];
	return true;
}

//判空
bool Isempty(PStack ps)
{
	return ps->top == 0;
}

//判满
bool Isfull(PStack ps)
{
	return ps->top == ps->stack_size;
}

//扩容
static void Inc(PStack ps)
{
	assert(ps != NULL);
	if (ps == NULL)
	{
		return;
	}
	//当前面的参数为0,相当于malloc,后边参数为0,相当于free
	ps->base = (ELEM_TYPE *)realloc(ps->base, ps->stack_size * sizeof(struct stack)*2);//前边变量放原先的空间的地址,后边变量放需要扩容后的总大小
	assert(ps->base != NULL);//内存扩容成功
	ps->stack_size *= 2;

}

//获取有效长度
int Get_length(PStack ps)
{
	return ps->top;//代表当前总个数,也代表下一个值的插入位置
}

//清空    不需要释放malloc申请的空间,只需要将栈顶指针改为0,则认为里面数据都失效
void Clear(PStack ps)
{
	ps->top = 0;
}

//销毁   需要释放malloc申请的空间
void Destroy(PStack ps)
{
	assert(ps != NULL);
	if (ps == NULL)
	{
		return;
	}
	free(ps->base);
	ps->base = NULL;//防止野指针
	ps->stack_size = ps->top = 0;
}

//打印
void Show(PStack ps)
{
	for (int i = 0; i < ps->top; i++)
	{
		printf("%d ", ps->base[i]);
	}
	printf("\n");
}

main主函数

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include"stack.h"

int main()
{
	struct stack ps;
	Init_stack(&ps);
	for (int i = 0; i < 15; i++)
	{
		Push(&ps, i + 1);
	}
	Show(&ps);
	printf("length=%d\n", Get_length(&ps));
	printf("stack_size=%d\n", ps.stack_size);

	ELEM_TYPE tmp;
	bool tag1 = false;
	tag1 = Pop(&ps, &tmp);
	if (tag1)
	{
		printf("tmp=%d\n", tmp);
	}
	Show(&ps);
	ELEM_TYPE tmp2;
	bool tag2 = Top(&ps, &tmp2);
	if (tag2)
	{
		printf("tmp2=%d\n", tmp2);
	}
	Show(&ps);

	Clear(&ps);
	printf("length=%d\n", Get_length(&ps));
	printf("stack_size=%d\n", ps.stack_size);

	Destroy(&ps);
	//Destroy(&ps);//可以销毁两次,是因为处理野指针了
	return 0;
}

运行结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值