栈的c语言实现

4. 栈

4.1 栈的概念及结构

栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。

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

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

请添加图片描述

4.2 栈的实现

1 正式的栈

基本信息

用于动态申请内存的指针

栈顶。一般由整型变量担任。

容量。一般由整型变量担任。

功能

初始化栈(Init)

指针置空。

栈顶指向栈底。这里有两种处理方式:

假设int top;为表示栈顶的变量,int *a;为动态数组,int t;为即将入栈的元素。

  1. 若栈顶元素初始化为top = 0,则尽量使用a[top++] = t;表示入栈。此时栈顶元素为a[top-1]
  2. 若栈顶元素初始化为top = -1,则尽量使用a[++top] = t;表示入栈。此时栈顶元素为a[top]

两种处理方式不能同时用,最好坚持一种风格。

栈容量置空。

销毁栈(destroy)

释放alloc系列函数(malloc,calloc,realloc以及c++关键字new)在堆区申请的空间并将指针置空。

栈顶元素和容量恢复初始值。

入栈(push)

假设int top;为表示栈顶的变量,int *a;为动态数组,int t;为即将入栈的元素。

  1. 若栈顶元素初始化为top = 0,则尽量使用a[top++] = t;表示入栈。此时栈顶元素为a[top-1]
  2. 若栈顶元素初始化为top = -1,则尽量使用a[++top] = t;表示入栈。此时栈顶元素为a[top]

这里以第1种风格为例。

首先判断栈顶元素和容量是否相等(即判断栈是否已满)。若满了则要进行有限的扩容。

后按照风格1入栈。

出栈(pop)

栈顶元素自减1即可。

返回栈顶元素(top)

假设int top;为表示栈顶的变量,int *a;为动态数组,int t;为即将入栈的元素。

  1. 若栈顶元素初始化为top = 0,则尽量使用a[top++] = t;表示入栈。此时栈顶元素为a[top-1]
  2. 若栈顶元素初始化为top = -1,则尽量使用a[++top] = t;表示入栈。此时栈顶元素为a[top]

若使用风格1,则返回a[top-1]

若使用风格2,则返回a[top]

判断栈是否为空(empty)

假设int top;为表示栈顶的变量,int *a;为动态数组,int t;为即将入栈的元素。

  1. 若栈顶元素初始化为top = 0,则尽量使用a[top++] = t;表示入栈。此时栈顶元素为a[top-1]
  2. 若栈顶元素初始化为top = -1,则尽量使用a[++top] = t;表示入栈。此时栈顶元素为a[top]

若使用风格1,则当top == 0时栈为空。

若使用风格2,则当top == -1时栈为空。

返回栈中元素(size)

假设int top;为表示栈顶的变量,int *a;为动态数组,int t;为即将入栈的元素。

  1. 若栈顶元素初始化为top = 0,则尽量使用a[top++] = t;表示入栈。则栈中元素数为top-1
  2. 若栈顶元素初始化为top = -1,则尽量使用a[++top] = t;表示入栈。则栈中元素数为top

2 栈的参考程序

Stack.h

#pragma once
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>

typedef int STDataType;
typedef struct Stack {
	STDataType* a;
	int top;//栈顶位置
	int capacity;
}ST;

void STInit(ST* pst);//初始化栈
void STDestroy(ST* pst);//销毁栈
void STPush(ST* pst, STDataType x);//数据入栈
void STPop(ST* pst);//删除栈顶元素
STDataType STTop(ST* pst);//返回栈顶元素
bool STEmpty(ST* pst);//判断栈是否为空
int STSize(ST* pst);//返回栈的元素个数

Stack.c

#include "Stack.h"

void STInit(ST* pst) {//初始化栈 
	assert(pst);//真实存在的栈才能被初始化 
	pst->a = NULL;

	//pst->top = -1;   // top 指向栈顶数据
	pst->top = 0;   // top 指向栈顶数据的下一个位置

	pst->capacity = 0;//栈中元素数初始化为0 
}

void STDestroy(ST* pst) {//销毁栈 
	assert(pst);

	free(pst->a);//销毁alloc开辟在堆区的内存 
	pst->a = NULL;
	pst->top = pst->capacity = 0;
}

void STPush(ST* pst, STDataType x) {//入栈
	if (pst->top == pst->capacity) {
		int newCapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;//线性表式扩容,因为栈也是特殊的线性表
		STDataType* tmp = (STDataType*)realloc(pst->a, newCapacity * sizeof(STDataType));
		if (tmp == NULL) {
			perror("realloc fail");
			return;
		}

		pst->a = tmp;
		pst->capacity = newCapacity;
	}

	pst->a[pst->top] = x;
	pst->top++;//因为栈顶要指向下一个元素 
}

void STPop(ST* pst) {//出栈
	assert(pst);
	assert(!STEmpty(pst));//栈不应该为空 

	pst->top--;//top指向栈顶元素的下一个位置,则退一格即可 
}

STDataType STTop(ST* pst) {//返回栈顶元素 
	assert(pst);
	assert(!STEmpty(pst));

	return pst->a[pst->top - 1];
	//之前top指向栈顶元素的下一个位置 
}

bool STEmpty(ST* pst) {//判断栈是否为空
	assert(pst);

	/*if (pst->top == 0) {
		return true;
	}
	else {
		return false;
	}*/

	return pst->top == 0;
}

int STSize(ST* pst) {//返回栈中元素数量 
	assert(pst);

	return pst->top;
}

3 简化的栈

根据上方栈的描述,我们完全可以省略大部分功能,弄一个临时的栈:

int a[1000]={0};//静态数组表示栈,但容量固定。可根据实际情况开辟。类型可更换。
int top=0;//栈顶元素,这里采用风格1,则栈顶元素即为a[top-1]。

//之后写几个函数作为栈的接口即可
void push(int x){//风格1入栈
    a[top]=x;
    top++;
}
void pop(){//出栈
    top--;
}
int size(){//返回栈的元素数
    return top;
}
//其他功能可自行补充

4.3 栈的应用

这里简单举个例子。

原题地址:http://ybt.ssoier.cn:8088/problem_show.php?pid=1354

1354:括弧匹配检验
时间限制: 1000 ms 内存限制: 65536 KB

【题目描述】

假设表达式中允许包含两种括号:圆括号和方括号,其嵌套的顺序随意,如([]())[([ ][ ])]等为正确的匹配,[( ])([ ]( ) ( ( ) ) )均为错误的匹配。

现在的问题是,要求检验一个给定表达式中的括弧是否正确匹配?

输入一个只包含圆括号和方括号的字符串,判断字符串中的括号是否匹配,匹配就输出 “OK” ,不匹配就输出“Wrong”。输入一个字符串:[([][])],输出:OK

【输入】

输入仅一行字符(字符个数小于255)。

【输出】

匹配就输出 “OK” ,不匹配就输出“Wrong”。

【输入样例】

[(])

【输出样例】

Wrong

分析:遍历题解给的字符串,是左括号则入栈,是右括号则判断栈顶元素是否与该括号匹配,若匹配则出栈,不匹配则整个字符串不匹配。

若遍历完所有的字符串,栈中还有剩余的左括号,则整个字符串不匹配。

参考程序:

#include<stdio.h>
#include<string.h>
int main () {
	char str[256];
	scanf("%[^\n]",str);
	int len=strlen(str);
    
    //一个数组和一个整型变量就能模拟一个栈的基本功能
	char str2[256]={0};                 //栈本体 
	int po=0;                           //栈顶 
    
    
	for(int i=0;i<len;i++) {
		if((str[i]=='[')||(str[i]=='(')) {//左括号入栈
			str2[po]=str[i];            //风格1入栈
			po++;
			continue;
		}
		else if(str[i]==')') {//右括号则观察是否和栈顶元素匹配
			if(str2[po-1]=='(') {
				str2[po-1]=0;
				po--;                   //风格1出栈
				continue;
			}
			printf("Wrong");
			return 0;
		}
		else if(str[i]==']') {
			if(str2[po-1]=='[') {
				str2[po-1]=0;
				po--;
				continue;
			}
			printf("Wrong");
			return 0;
		}
	}
	if(po==0)//判断栈是否为空
		printf("OK");
	else
		printf("Wrong");
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Darkwanderor

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

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

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

打赏作者

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

抵扣说明:

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

余额充值