IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 栈的实现(后有完整经过测试的代码需要可以自取) -> 正文阅读

[数据结构与算法]栈的实现(后有完整经过测试的代码需要可以自取)

零.前言

栈作为一种数据结构是一种特殊的顺序表,即规定只能在·末尾·进行插入和删除,栈和队列的提出实际是为了减少思考量,比如你发现某个存储结构满足栈的特点,那就不用考虑进行什么头插头删和查找等操作了,直接把想要实现的操作(比如顺序表)写成栈就可以了。

1.栈的特点

栈是一种存储数据的结构,只支持后进先出,通常用顺序表来进行栈的实现。我们实现栈只需要遵循一个原则就是后进后出就足够了。

2.栈的结构

1.逻辑结构

在这里插入图片描述
只能从顶部进行插入和删除。

2.物理结构

物理结构和顺序表时一样的,都是用数组来存储数据。

3.栈的基本操作

1.建立一个栈

typedef struct stack {
	DataType* a;
	int top;
	int capacity;
}ST;

*a表示的是指向栈中元素的指针,top表示指向的栈顶元素的前一个元素,这是因为在进行栈的插入之后top会进行++操作,所以top始终表示的是栈顶元素的前一个元素,进行-1才能获得栈顶的元素。capacity表示的是栈的最大容量,如果容量不够需要进行扩容操作。

2.栈的初始化

void StackInit(ST* ps)
{
	assert(ps);
	ps->a = NULL;
	ps->top = 0;//top指针指向栈顶的元素
	ps->capacity = 0;//capacity表示的是栈的最大容量
}

栈的初始化即将指针a置为空,将top和capacity置为0.

3.栈的销毁

栈的销毁即将栈中指针所指向空间进行释放,然后将指针置为空,其他值置为0即可。

void StackDestroy(ST* ps)
{
	assert(ps);
	free(ps->a);
	ps->a = NULL;
	ps->top = ps->capacity = 0;
}

4.打印一个栈

打印一个栈,就要通过top对栈进行遍历,top每进行一次–就进行一次打印。

void PrintStack(ST* ps)
{
	assert(ps);
	int top2 = ps->top;
	while (ps->top>0)
	{
		printf("%d ", ps->a[--ps->top]);
	}
	ps->top = top2;
	printf("\n");	
}

5.判断栈的大小

栈的大小和top有关,因为top表示的是栈顶元素,top-1即为栈的大小。

int StackSize(ST* ps)
{
	assert(ps);
	return ps->top;
}

6.判断栈是否为空

由于栈的大小和top有关,所以判断栈是否为空就是判断top是否大于0。

bool StackEmpty(ST* ps)
{
	assert(ps);
	return ps->top == 0;
}

这里用的是一个布尔表达式来接收,如果top为0则返回true说明栈为空,如果top大于0,则返回false说明栈不为空。

7.得到栈顶元素

栈顶元素就是top-1表示的元素,其实栈的所有操作都和这个top有关,因为栈只支持后进先出,只需要对栈顶进行研究即可。

int StackTop(ST* ps)
{
	assert(ps);
	assert(ps->top > 0);
	return ps->a[ps->top - 1];
}

4.栈的插入和删除

1.栈的插入

在进行栈的插入时,我们就需要考虑栈的容量够不够大,即top和capacity的大小关系,如果空间不够则需要进行扩容,我们规定当栈为空时,为其分配四个空间,当栈不为空时为其分配原来二倍的空间。在进行插入时,通过对栈顶指针的修改即可实现。我们在堆区进行插入,方便在删除栈时释放空间。

void StackPush(ST* ps, DataType x)
{
	assert(ps);
	if (ps->top == ps->capacity)
	{
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		DataType* tmp = (DataType*)realloc(ps->a, sizeof(DataType) * newcapacity);
		if (tmp == NULL)
		{
			printf("realloc fail\n");
			exit(-1);
		}
		ps->a = tmp;
		ps->capacity = newcapacity;
	}
	ps->a[ps->top] = x;
	ps->top++;
}

2.栈的删除

栈的删除操作也是在栈顶进行的,只需要将栈顶指针–即可。同时还要保障栈存在且栈不为空。

void StackPop(ST* ps)
{
	assert(ps);
	assert(ps->top > 0);
	ps->top--;
}

5.栈的实现

1.ST.h文件

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
#define DataType int
typedef struct stack {
	DataType* a;
	int top;
	int capacity;
}ST;
void StackInit(ST* ps);
void StackDestroy(ST* ps);
bool StackEmpty(ST* ps);
int StackSize(ST* ps);
void StackPush(ST* ps,DataType x);
void StackPop(ST* ps);
int StackTop(ST* ps);
void PrintStack(ST* ps);

2.ST.c文件

#define _CRT_SECURE_NO_WARNINGS 1
#include "ST.h"
void StackInit(ST* ps)
{
	assert(ps);
	ps->a = NULL;
	ps->top = 0;
	ps->capacity = 0;
}
void StackDestroy(ST* ps)
{
	assert(ps);
	free(ps->a);
	ps->a = NULL;
	ps->top = ps->capacity = 0;
}
bool StackEmpty(ST* ps)
{
	assert(ps);
	return ps->top == 0;
}
int StackSize(ST* ps)
{
	assert(ps);
	return ps->top;
}
void StackPush(ST* ps, DataType x)
{
	assert(ps);
	if (ps->top == ps->capacity)
	{
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		DataType* tmp = (DataType*)realloc(ps->a, sizeof(DataType) * newcapacity);
		if (tmp == NULL)
		{
			printf("realloc fail\n");
			exit(-1);
		}
		ps->a = tmp;
		ps->capacity = newcapacity;
	}
	ps->a[ps->top] = x;
	ps->top++;
}
void StackPop(ST* ps)
{
	assert(ps);
	assert(ps->top > 0);
	ps->top--;
}
int StackTop(ST* ps)
{
	assert(ps);
	assert(ps->top > 0);
	return ps->a[ps->top - 1];
}
void PrintStack(ST* ps)
{
	assert(ps);
	int top2 = ps->top;
	while (ps->top>0)
	{
		printf("%d ", ps->a[--ps->top]);
	}
	ps->top = top2;
	printf("\n");	
}

3.test.c文件

#define _CRT_SECURE_NO_WARNINGS 1
#include"ST.h"
void menu()
{
	printf("****1.入栈****2.出栈****\n");
	printf("****3.栈顶元素4.栈是否为空**\n");
	printf("****5.栈的大小0.销毁****\n");
}
int main()
{
	ST ps;
	StackInit(&ps);
	StackPush(&ps, 1);
	StackPush(&ps, 2);
	StackPush(&ps, 3);
	StackPush(&ps, 4);
	StackPush(&ps, 5);
	PrintStack(&ps);
	int input = 0;
	do
	{
		menu();
		int x;
		scanf("%d", &input);
		switch (input)
		{
		case 1:scanf("%d", &x);
			StackPush(&ps, x);
			PrintStack(&ps);
			break;
		case 2:StackPop(&ps);
			PrintStack(&ps);
			break;
		case 3:
			x = StackTop(&ps);
			printf("%d\n", x);
			break;
		case 4:
		if (StackEmpty(&ps) == 0)
		{
			printf("not empty\n");
		}
		 else 
	    {
			printf("empty\n");
		}
		break;
		case 5:
			x = StackSize(&ps);
			printf("%d\n", x);
			break;
		case 0:
			StackDestroy(&ps);
			break;
		default:printf("error type\n");
			break;
		}
	} while (input);
	return 0;
}

6.测试

1.插入:成功
2.删除至空报错:成功
3.得到栈顶元素无栈顶元素报错:成功
4.销毁栈:成功
综上:代码测试成功

7.总结

顺序表,链表,栈和队列都是简单的数据结构,在学习过程中只需要把握住指针即可,就像栈一样,把栈顶指针搞明白的话基本可以解决大部分问题,无论是插入删除判断栈空都需要使用到栈顶的指针。

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-11-14 21:58:23  更:2021-11-14 21:59:06 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 10:42:34-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码