C/C++ 数据结构 —— 栈

在这里插入图片描述

在这里插入图片描述

🎁个人主页:工藤新一¹

🔍系列专栏:C++面向对象(类和对象篇)

​ 🌟心中的天空之城,终会照亮我前方的路

🎉欢迎大家点赞👍评论📝收藏⭐文章

一、栈的概念

1.1概念与结构

:是一种只允许在固定的一段 (栈顶)进行插入和删除元素操作的线性表访问受限的线性表,任何操作都必须在线性表的最后栈顶)面执行)。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵循着后进先出**LIFO(Last In First Out)**的原则。

**压栈:**栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶

**出栈:**栈的删除操作叫做出栈,出数据也在栈顶

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

  • 逻辑结构上:线性的
  • 物理结构上:数组实现的栈是线性的,由链表实现的栈一般是非线性的

二、数组实现栈

在这里插入图片描述

在这里插入图片描述


2.1栈的定义与初始化

C

//定义栈数据
	typedef int STDataType;
	typedef struct Stack
	{
		STDataType* arr;
		int top;//有效元素个数(指向栈顶位置)
		int capacity;//栈的容量
	}ST;

//为栈中数据进行初始化
	void StackInit(ST* ps)
	{
		ps->arr = NULL;
		ps->top = ps->capacity = 0;
	}


2.2入栈、出栈

  • Stack.h
C
    //入栈
	void StackPush(ST* ps, STDataType x);

	//出栈
	void StackPop(ST* ps)

  • Stack.cpp
C
    void StackPush(ST* ps, STDataType x)
	{
		assert(ps);
		if (ps->top == ps->capacity)
		{
			//增容,if(ps->capacity == 0)向内存申请 4 个 STDataType 类型的空间
			int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
			STDataType* temp = (STDataType*)realloc(ps->arr, newCapacity * sizeof(STDataType));
	
			if (temp == NULL)
			{
				perror("realloc fail!");
				exit(1);
			}
			ps->arr = temp;
			ps->capacity = newCapacity;
		}

		ps->arr[ps->top++] = x;
	}

	//判空操作
	bool StackEmpty(ST* ps)
	{
		assert(ps);
		return ps->top == 0;//为空,返回true
	}


	void StackPop(ST* ps)
	{
		//assert(!true) - false 终止代码运行
		assert(!StackEmpty(ps));//保证 ps 不为空,才能执行以下操作
		/*
		断言:
			条件为true,程序继续执行
			条件为false,程序会终止
		*/
		ps->top--;
	}

2.3出栈顶数据、获取栈中有效元素个数

  • Stack.h
C
    //出栈顶数据
	STDataType StackTop(ST* ps);

	//获取栈中有效元素个数
	int StackSize(ST* ps);

  • Stack.cpp
C
    STDataType StackTop(ST* ps)
	{
		assert(!StackEmpty(ps));
		return ps->arr[ps->top - 1];
	}

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

2.4销毁栈

  • Stack.h
C 
	//销毁栈
	void StackDestroy(ST* ps);

  • Stack.cpp
C
    void StackDestroy(ST* ps)
	{
		if (ps->arr)
			free(ps->arr);

		ps->arr = NULL;
		ps->capacity = ps->capacity == 0;
	}

三、数据删除 ---- 对顺序表、链表的理解

  • 删除数据不需要 free 吗 ?

在先前讲解链表时,我们每删除一个节点,就会 free 回收掉该节点,那为什中不执行这样的操作呢? (而是,ps->top–)

  • 因为的底层是一个数组数组的存储空间是连续的),如果 free(arr) 那么就会将以 ps->arr 为起始地址后的所有数据全部释放掉

  • 为什么在链表中可以一个一个的销毁呢?

  • 因为链表的存储结构是由一个个相互独立的节点组成的,free 掉其中一个节点,并不会影响其他节点


四、栈代码

  • Stack.h
C
#pragma once

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
#include<iostream>
using namespace std;


typedef int STDataType;
typedef struct Stack
{
	STDataType* arr;
	int top;//有效元素个数(指向栈顶位置)
	int capacity;//栈的容量
}ST;

//使形参可以影响实参 - 地址传递 - 指针接收
void StackInit(ST* ps);

//入栈
void StackPush(ST* ps, STDataType x);

//出栈
void StackPop(ST* ps);

//判空 - 栈是否为空
bool StackEmpty(ST* ps);

//出栈顶数据
STDataType StackTop(ST* ps);

//获取栈中有效元素个数
int StackSize(ST* ps);

//销毁栈
void StackDestroy(ST* ps);

  • test.c
C
#include"Stack.h"

void test01()
{
	ST st;
	StackInit(&st);
	StackPush(&st, 10);
	StackPush(&st, 20);
	StackPush(&st, 30);
	StackPush(&st, 40);
	StackPush(&st, 50);
	StackPop(&st);
	//StackPop(&st);
	//StackPop(&st);
	//StackPop(&st);
	//StackPop(&st);
	//while(!StackEmpty(&st))//如果栈不为空
	//{
		//int top = StackTop(&st);
		//printf("%d ", top);
		//StackPop(&st);
	//}

	int size = StackSize(&st);
	printf("%d\n", size);//栈中有效元素个数

	StackDestroy(&st);

	string s; 
	isValid(s);
}
int main()
{
	test01();
	return 0;
}    

  • Stack.cpp
C
#include"Stack.h"

void StackInit(ST* ps)
{
	ps->arr = NULL;
	ps->top = ps->capacity = 0;
}


void StackPush(ST* ps, STDataType x)
{
	assert(ps);
	if (ps->top == ps->capacity)
	{
		//增容,if(ps->capacity == 0)向内存申请 4 个 STDataType 类型的空间
		int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		STDataType* temp = (STDataType*)realloc(ps->arr, newCapacity * sizeof(STDataType));
	
		if (temp == NULL)
		{
			perror("realloc fail!");
			exit(1);
		}
		ps->arr = temp;
		ps->capacity = newCapacity;
	}

	ps->arr[ps->top++] = x;
}

//判空操作
bool StackEmpty(ST* ps)
{
	assert(ps);
	return ps->top == 0;//为空,返回true
}


void StackPop(ST* ps)
{
	//assert(!true) - false 终止代码运行
	assert(!StackEmpty(ps));//保证 ps 不为空,才能执行以下操作
	/*
	断言:
		条件为true,程序继续执行
		条件为false,程序会终止
	*/
	ps->top--;
}

STDataType StackTop(ST* ps)
{
	assert(!StackEmpty(ps));
	return ps->arr[ps->top - 1];
}

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

void StackDestroy(ST* ps)
{
	if (ps->arr)
		free(ps->arr);

	ps->arr = NULL;
	ps->capacity = ps->capacity == 0;
	
}

  • OJ - 有效括号
C
    typedef char STDataType;
	bool isValid(char* s)
	{
		ST st;
		StackInit(&st);

		char* pi = s;
		while (pi != '\0')
		{
			if (*pi == '(' || *pi == '[' || *pi == '{')
			{
				StackPush(&st, *pi);
			}
			else
			{
				if (StackEmpty(&st)) return false;
	
				if ((*pi == ')' && StackTop(&st) != '(')
					|| (*pi == ']' && StackTop(&st) != '[')
					|| (*pi == '}' && StackTop(&st) != '{'))
				{
					StackDestroy(&st);
					return false;
                }

				StackPop(&st);
			}
			pi++;
		}

		bool ret = StackEmpty(&st) ? true : false;
		StackDestroy(&st);
        
		return ret;
	}

🌟 各位看官好,我是工藤新一¹呀~

🌈 愿各位心中所想,终有所致!
在这里插入图片描述

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值