数据结构——栈

目录

1、栈的基本概念

2、栈的基本功能

3、栈的实现

        1、数组栈

        2、链式栈


1、栈的基本概念

        栈是一种数据结构,用来存储数据,只能在栈顶插入和删除数据,

可以看到这个栈的空间是需要不断开辟的,因此我们需要一个能动态改变大小的结构,我们可以用

柔性数组或者用链表,但是链表一般只有头结点,我们要在尾部插入,就只能先遍历一次数组,影响效率,所以我们将头结点作为栈顶。

2、栈的基本功能

1、入栈(Leave):将新的元素添加到栈的顶部。

2、出栈(Enter):从栈的顶部移除元素,并返回被移除的元素。

3、获取栈顶元素(Peek):返回栈顶的元素,但不对栈进行修改。

4、判断栈是否为空(IsEmpty):检查栈是否为空,即判断栈中是否没有元素。

5、获取栈的大小(Size):返回栈中元素的个数。

6、初始化栈(Initialize):如果是链表就清空链表,如果是数组就初始化数组。

3、栈的实现

如果用数组

先看看头文件

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
typedef int Data;//可以更改数据类型
typedef struct s
{
	Data* x;//数组名
	int top;//这个用来看元素个数
	int size;//这个用来看数组的大小
}TSN;//这个结构体是一个柔性数组
void SLLeave(TSN* ptop, Data x);//入栈
Data SLEnter(TSN* ptop);//出栈
int SLSize(TSN* ptop);//查看栈的元素个数
Data SLPeek(TSN* ptop);//获取栈顶元素
void SLInitialize(TSN* ptop);//初始化
bool STEmpty(TSN* ptop);//判空

先创建一个柔性数组

TSN top = { NULL,-1,0 };//top给-1是有原因的

1、入栈(Leave)

void SLLeave(TSN* ptop, Data x)//入栈
{
	assert(ptop);
	Data* a = ptop->x;
	if (a == NULL)//如果数组还没有开辟
	{
		a = (Data*)malloc(sizeof(Data));//就先开一个位置
		assert(a);//我们要查看是否开辟成功,因为malloc函数没有
				//开辟成功会返回空指针
		ptop->x = a;//入栈
		a[ptop->top+1] = x;//数组下标从0开始,如果top为0
		ptop->top++;//++变为1,top指向的就是第二个元素,我让top
					//指向的是栈顶元素
		ptop->size = 1;
		return;
	}
	if (ptop->top == ptop->size - 1)//如果数组已经满了
	{
		a = realloc(ptop->x,2 * (ptop->size) * sizeof(Data));//扩容
		assert(a);//同malloc函数一样,没有开辟成功会返回空指针
		ptop->x = a;
		a[ptop->top + 1] = x;
		ptop->top++;
		ptop->size = 2 * (ptop->size);//size变为2倍
		return;
	}
	else//数组还有空间
	{
		a[ptop->top + 1] = x;
		ptop->top++;
	}
}

2、出栈(Enter)

Data SLEnter(TSN* ptop)//出栈
{
	assert(ptop);
	if (STEmpty(ptop))//如果栈为空,为空出什么出
	{
		printf("is empty\n");//告诉他为空
		assert(0);//就报警
	}
	else//如果栈不为空
	{
		ptop->top--;
		return ptop->x[ptop->top+1];//就出一个数据
	}
}

3、获取栈顶元素(Peek):返回栈顶的元素,但不对栈进行修改。)

Data SLPeek(TSN* ptop)//
{
	assert(ptop);
	if (STEmpty(ptop))//同样判段栈是否为空
	{
		printf("is empty\n");
		assert(0);//提示加报警
	}
	return ptop->x[ptop->top];//不为空就返回栈顶元素
							//但不进行修改栈
}

4、判断栈是否为空(IsEmpty):检查栈是否为空,即判断栈中是否没有元素。

bool STEmpty(TSN* ptop)//判空
{
	if (ptop->top == -1)
		return true;
	return false;
}

5、获取栈的大小(Size):返回栈中元素的个数。

int SLSize(TSN* ptop)
{
	return ptop->top+1;//top是数组下标
}

6、初始化栈(Initialize):如果是链表就清空链表,如果是数组就初始化数组。

void SLInitialize(TSN* ptop)
{
	ptop->top = -1;//因为数组空间不可以局部释放,只能全部释放
					//那我们就不让它访问就好了
}
#include"test.h"
int main()
{
	TSN top = { NULL,-1,0 };//top给-1是有原因的
	SLLeave(&top, 1);
	SLLeave(&top, 2);
	SLLeave(&top, 3);
	SLLeave(&top, 4);
	/*SLInitialize(&top);*/
	printf("%d\n",SLEnter(&top));//出栈
	printf("%d\n", SLEnter(&top));//出栈
	printf("%d\n", SLEnter(&top));//出栈
	printf("%d\n", SLPeek(&top));//获取栈顶元素
	printf("%d\n", SLEnter(&top));//出栈
	printf("%d\n", SLSize(&top));
	return 0;
}

如果使用链表

先看头文件

#define _CRT_SECURE_NO_WARNINGS
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
typedef int typeData;
typedef struct SLStack
{
	int top;//记录个数
	typeData x;//我们的数据
	struct SLStack* next;
}TSS;//这是储存元素的节点
typedef struct STPointer
{
	TSS* stack_head;
	int size;
}TSP;//为了方便我们创一个哨兵

typeData SLEnter(TSP* top);//出栈
void SLLeave(TSP* top,int x);//入栈
void STprint(TSP* top);//看看这个栈
bool STEmpty(TSP* top);//判空
int  STSize(TSP* top);//查看栈的元素个数
int STInitialize(TSP* top);//初始化
void STSentry(TSP** ptop);//创建哨兵

1、入栈(Leave):将新的元素添加到栈的顶部。

void SLLeave(TSP* top,int x)//入栈(其实是头插)
{
	assert(top);
	TSS* newtop = Add(x);
	assert(newtop);
	if (top->stack_head==NULL)//栈为空
	{
		top->stack_head = newtop;//入栈
		newtop->x = x;
	}
	else//栈已经有元素了
	{//直接链接
		newtop->next = top->stack_head;
		top->stack_head = newtop;
	}
	top->size++;//size需要实时更新
}

2、出栈(Enter):从栈的顶部移除元素,并返回被移除的元素。

typeData SLEnter(TSP* top)//出栈
{
	assert(top);
	assert(top->stack_head);//空栈时在出栈直接报警
	typeData a = top->stack_head->x;
	TSS* tmp = top->stack_head;//先存着,等下要释放
	/*if (top->size == 1)可能你会觉得只有一个结点时
	*再出栈时要把top->stack_head置为指针,其实我在
	* 申请结点是就已经做了初始化,只有一个结点时
	* top->stack_head->next=NULL。
	{
		free(top->stack_head);
		top->stack_head = NULL;
		top->size--;
		return a;
	}*/
	top->stack_head = top->stack_head->next;
	top->size--;//size需要实时更新
	free(tmp);//不释放会造成内存泄漏
	return a;//返回结点数据
}

3、获取栈顶元素(Peek):返回栈顶的元素,但不对栈进行修改。

typeData SLPeek(TSP* top)//查看栈顶元素
{
	assert(top);
	assert(top->stack_head);//空栈时直接报警
	typeData a = top->stack_head->x;
	return a;
}

4、判断栈是否为空(IsEmpty):检查栈是否为空,即判断栈中是否没有元素。

bool STEmpty(TSP* top)//检查栈是否为空,即是否没有任何元素。
{
	if (top->stack_head == NULL)
		return true;
	return false;
}

5、获取栈的大小(Size):返回栈中元素的个数。

int  STSize(TSP* top)//获取栈中当前元素的个数
{
	assert(top);
	return top->size;
}

6、初始化栈(Initialize):如果是链表就清空链表,如果是数组就初始化数组。

void STInitialize(TSP* top)//初始化
{
	if (!STEmpty(top))//如果不是空栈
	{
		TSS* a = top->stack_head;
		while (a)//循环销毁
		{
			TSS* tmp=a->next;//先保存下一个结点
			free(a);
			a = tmp;
		}
	}
	else//空栈直接告诉我
	{
		printf("empty\n");
	}
}

完整代码

//头文件
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
typedef int typeData;
typedef struct SLStack
{
	typeData x;//我们的数据
	struct SLStack* next;
}TSS;//这是储存元素的节点
typedef struct STPointer
{
	TSS* stack_head;
	int size;
}TSP;//为了方便我们创一个哨兵

typeData SLEnter(TSP* top);
void SLLeave(TSP* top,int x);
void STprint(TSP* top);
bool STEmpty(TSP* top);
int  STSize(TSP* top);
void STInitialize(TSP* top);
void STSentry(TSP** ptop);
//函数定义.c文件
#include"stack.h"
TSS* Add(typeData x)
{
	TSS* newtop = (TSS*)malloc(sizeof(TSS));
	assert(newtop);
	newtop->next = NULL;
	newtop->x = x;
	return newtop;
}
void STSentry(TSP** ptop)
{
	assert(ptop);
	(*ptop) = (TSP*)malloc(sizeof(TSP));
	assert(*ptop);
	(*ptop)->size = 0;
	(*ptop)->stack_head = NULL;
}
bool STEmpty(TSP* top)//检查栈是否为空,即是否没有任何元素。
{
	if (top->stack_head == NULL)
		return true;
	return false;
}
void STInitialize(TSP* top)//初始化
{
	if (!STEmpty(top))//如果不是空栈
	{
		TSS* a = top->stack_head;
		while (a)//循环销毁
		{
			TSS* tmp=a->next;//先保存下一个结点
			free(a);
			a = tmp;
		}
	}
	else//空栈直接告诉我
	{
		printf("empty\n");
	}
}
void SLLeave(TSP* top, int x)//入栈
{
	assert(top);
	TSS* newtop = Add(x);
	assert(newtop);
	if (top->stack_head == NULL)//栈为空
	{
		top->stack_head = newtop;//入栈
		newtop->x = x;
	}
	else//栈已经有元素了
	{//直接链接
		newtop->next = top->stack_head;
		top->stack_head = newtop;
	}
	top->size++;//size需要实时更新
}

typeData SLEnter(TSP* top)//出栈
{
	assert(top);
	assert(top->stack_head);//空栈时在出栈直接报警
	typeData a = top->stack_head->x;
	TSS* tmp = top->stack_head;//先存着,等下要释放
	/*if (top->size == 1)可能你会觉得只有一个结点时
	*再出栈时要把top->stack_head置为指针,其实我在
	* 申请结点是就已经做了初始化,只有一个结点时
	* top->stack_head->next=NULL。
	{
		free(top->stack_head);
		top->stack_head = NULL;
		top->size--;
		return a;
	}*/
	top->stack_head = top->stack_head->next;
	top->size--;//size需要实时更新
	free(tmp);//不释放会造成内存泄漏
	return a;//返回结点数据
}
typeData SLPeek(TSP* top)//查看栈顶元素
{
	assert(top);
	assert(top->stack_head);//空栈时直接报警
	typeData a = top->stack_head->x;
	return a;
}
void STprint(TSP* top)
{
	assert(top);
	TSS* a = top->stack_head;
	while (a != NULL)
	{
		printf("%d ", a->x);
		a = a->next;
	}
}
int  STSize(TSP* top)//获取栈中当前元素的个数
{
	assert(top);
	return top->size;
}
//主函数.c文件
#include"stack.h"
int main()
{
	TSP* topp = NULL;
	STSentry(&topp);//哨兵
	/*printf("%d\n", SLEnter(topp));*/
	//STInitialize(topp);//初始化
	SLLeave(topp,1);//入栈
	
	SLLeave(topp, 2);
	printf("%d\n",SLEnter(topp));
	printf("%d\n", SLEnter(topp));//出栈并查看出栈数据
	
	SLLeave(topp, 3);
	printf("%d\n",STSize(topp));
	STInitialize(topp);//初始化
	//STprint(topp);//查看栈
	//STprint(topp);
	return 0;
}

数组栈更好实现。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值