数据结构 严薇敏 栈 的实现及其使用方法详解

本文详细介绍了如何使用C语言实现一个动态顺序栈,包括栈的初始化、入栈、出栈、获取栈顶元素、获取栈的大小、判断栈是否为空以及栈的销毁。同时,还实现了栈的扩容功能,当栈满时自动扩大一倍容量。在测试代码中展示了栈的各种操作,如压栈、弹栈、检查栈的状态等。
摘要由CSDN通过智能技术生成

目录

1.栈

1.1栈的概念及结构

1.2栈的实现

 1.3接口以及实现

Stack.h 

Stack.c

栈的初始化

入栈

出栈

获取栈顶元素

获取栈中有效元素的个数

检测栈是否为空

栈的销毁

扩容

测试


1.栈

1.1栈的概念及结构

栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。形象一点就是吃进去吐出来,只是在一端进行操作。
压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
出栈:栈的删除操作叫做出栈。出数据也在栈顶。
 

1.2栈的实现

栈的话用动态顺序表实现就是比较简单的,当然也可用单链表实现,但是注意一个问题,栈是不可以被遍历的,我们就用顺序表来实现

顺序结构

 链式结构

 1.3接口以及实现

Stack.h 

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
typedef int Datatype;

//其实就是一个阉割版的顺序表
//我们知道栈是先进后出,只要给他的操作遵循就好了

typedef struct Stack {
	//动态的栈
	Datatype* arr;
	int capacity;
	//标记栈顶
	int top;
}Stack;
//栈的初始化
void StackInit(Stack* p, int capacity);

//入栈
void StackPush(Stack* p, Datatype data);

//出栈
void StackPop(Stack* p);

//获取栈顶元素
Datatype Stacktop(Stack* p);

//获取栈的大小
int StackSize(Stack* p);

//判断栈是否为空
int StackEmpty(Stack* p);

//栈的销毁
void StackDestroy(Stack* p);

//栈的扩容 
//阉割版的顺序表呀在此就不再赘述
void StackCheckCapacity(Stack* p);

Stack.c

#include "Stack.h"
//栈的初始化
void StackInit(Stack* p, int capacity)
{
	//检测参数合法性
	assert(p);
	//对传入的capacity为负数的体现
	capacity = capacity <= 0 ? 3 : capacity;
	//动态在堆上申请空间来初始化栈
	p->arr = (Datatype* )malloc(sizeof(Stack) * capacity);
	//开辟未成功
	if (NULL == p->arr) {
		assert(0);
	}
	//更新参数
	p->capacity = capacity;
	p->top = 0;
}

//入栈
void StackPush(Stack* p, Datatype data)
{
	StackCheckCapacity(p);
	//直接压栈把data放在栈顶指针这块
	p->arr[p->top] = data;
	//栈顶指针++
	p->top++;
}
//出栈
void StackPop(Stack* p)
{
	//先得看看是否为空
	if (StackEmpty(p)) {
		return;
	}
	//栈顶指针--
	p->top--;
}
//获取栈顶元素
Datatype Stacktop(Stack* p)
{
	//先得看看是否为空
	assert(p);
	if (StackEmpty(p)) {
		return;
	}
	// return ps->arr[--p->top];  // 错误写法
	return p->arr[p->top - 1];
}

// 获取栈中有效元素的个数
int StackSize(Stack* p)
{
	//检测参数合法性
	assert(p);
	return p->top;
}

// 检测栈是否为空,如果为空返回真,否则返回假
int StackEmpty(Stack* p)
{
	//检测参数合法性
	assert(p);

	return 0 == p->top;
}

//栈的销毁
void StackDestroy(Stack* p)
{
	//检测参数合法性
	assert(p);
	//free掉防止内存泄露
	if (p->arr) {
		free(p->arr);
		p->capacity = 0;
		p->top = 0;
	}
}

//扩容
//先申请新的内存空间
//把原来的数据拷贝到新扩容的空间里面去
//free掉原来空间,让arr指向新开辟的内存空间
void StackCheckCapacity(Stack* p)
{
	//检测参数合法性
	assert(p);
	if (p->capacity == p->top) {
		int Newcapacity = (p->capacity << 1);
		Datatype* temp = (Datatype*)malloc(sizeof(Datatype) * Newcapacity);
		if (NULL == temp) {
			assert(0);
		}
		memcpy(temp, p->arr, sizeof(Datatype) * p->capacity);
		free(p->arr);
		p->arr = temp;
		p->capacity = Newcapacity;
	}
}
int main() {
	Stack s;
	StackInit(&s,3);

	StackPush(&s, 1);
	StackPush(&s, 2);
	StackPush(&s, 3);
	printf("size = %d\n", StackSize(&s));
	printf("top = %d\n", Stacktop(&s));

	StackPush(&s, 4);   // 扩容
	StackPush(&s, 5);
	StackPush(&s, 6);
	StackPush(&s, 7);  // 扩容
	printf("size = %d\n", StackSize(&s));
	printf("top = %d\n", Stacktop(&s));

	StackPop(&s);
	StackPop(&s);
	StackPop(&s);
	printf("size = %d\n", StackSize(&s));
	printf("top = %d\n", Stacktop(&s));
	StackDestroy(&s);
}

栈的初始化

//栈的初始化
void StackInit(Stack* p, int capacity)
{
	//检测参数合法性
	assert(p);
	//对传入的capacity为负数的体现
	capacity = capacity <= 0 ? 3 : capacity;
	//动态在堆上申请空间来初始化栈
	p->arr = (Datatype* )malloc(sizeof(Stack) * capacity);
	//开辟未成功
	if (NULL == p->arr) {
		assert(0);
	}
	//更新参数
	p->capacity = capacity;
	p->top = 0;
}
  1. assret我们的老朋友先对参数合法性判断。
  2. 然后对capacity合法性判断,如果是负数就给他一个初始值,c++用缺省参数就规避掉了给他一个默认值就好了。
  3. 在堆上申请空间,然后对申请的空间进行判断是否申请成功了。
  4. 再更新我们的参数。

入栈

//入栈
void StackPush(Stack* p, Datatype data)
{
    StackCheckCapacity(p);
	//直接压栈把data放在栈顶指针这块
	p->arr[p->top] = data;
	//栈顶指针++
	p->top++;
}
  1. 压栈把data放在栈顶部位。
  2. 在把站栈顶指针向上移动。

出栈

//出栈
void StackPop(Stack* p)
{
	//先得看看是否为空
	if (StackEmpty(p)) {
		return;
	}
	//栈顶指针--
	p->top--;
}
  1. 看看栈是否为空,要是空就直接返回,就不删除了。
  2. 然后栈顶指针向下移动。

获取栈顶元素

//获取栈顶元素
Datatype Stacktop(Stack* p)
{
	//先得看看是否为空
	assert(p);
	if (StackEmpty(p)) {
		return;
	}
	// return ps->arr[--p->top];  // 错误写法
	return p->arr[p->top - 1];
}
  1. 先判空是否为空栈。
  2. 减1让我们栈顶指针指向栈顶元素。
  3. 然后直接把栈顶元素返回就好了。

获取栈中有效元素的个数

// 获取栈中有效元素的个数
int StackSize(Stack* p)
{
	//检测参数合法性
	assert(p);
	return p->top;
}
  1. 直接把top输出传回来就好了。

检测栈是否为空

// 检测栈是否为空,如果为空返回真,否则返回假
int StackEmpty(Stack* p)
{
	//检测参数合法性
	assert(p);

	return 0 == p->top;
}
  1. 判断是否为空其实就是栈顶指针是否等于栈底指针。
  2. 这里我们0就是栈底指针 top就是栈顶指针相等就是空。

栈的销毁

//栈的销毁
void StackDestroy(Stack* p)
{
	//检测参数合法性
	assert(p);
	//free掉防止内存泄露
	if (p->arr) {
		free(p->arr);
		p->capacity = 0;
		p->top = 0;
	}
}
  1. 先检验参数合法性。
  2. 把这个栈free掉。
  3. 再把参数更新。

扩容

//扩容
//先申请新的内存空间
//把原来的数据拷贝到新扩容的空间里面去
//free掉原来空间,让arr指向新开辟的内存空间
void StackCheckCapacity(Stack* p)
{
	//检测参数合法性
	assert(p);
	if (p->capacity == p->top) {
		int Newcapacity = (p->capacity << 1);
		Datatype* temp = (Datatype*)malloc(sizeof(Datatype) * Newcapacity);
		if (NULL == temp) {
			assert(0);
		}
		memcpy(temp, p->arr, sizeof(Datatype) * p->capacity);
		free(p->arr);
		p->arr = temp;
		p->capacity = Newcapacity;
	}
}
  1. 开辟新的内存空间。
  2. 把数据拷贝到新空间去。
  3. 释放旧空间。
  4. p的arr指向新空间。

测试

void text() {
	Stack s;
	StackInit(&s, 3);

	StackPush(&s, 1);
	StackPush(&s, 2);
	StackPush(&s, 3);
	printf("size = %d\n", StackSize(&s));
	printf("top = %d\n", Stacktop(&s));

	StackPush(&s, 4);   // 扩容
	StackPush(&s, 5);
	StackPush(&s, 6);
	StackPush(&s, 7);  // 扩容
	printf("size = %d\n", StackSize(&s));
	printf("top = %d\n", Stacktop(&s));

	StackPop(&s);
	StackPop(&s);
	StackPop(&s);
	printf("size = %d\n", StackSize(&s));
	printf("top = %d\n", Stacktop(&s));
	StackDestroy(&s);
}

评论 23
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

五毛变向.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值