数据结构——栈(1)

目录

1.1 定义

1.2 创建动态数组

 1.3 栈初始化

1.4 栈的删除

1.5 向栈中插入元素(压栈)

1.6 从栈中删除元素(出栈)

1.7 判断栈是否为空

1.8 返回栈顶元素

1.9 进行测试(在 Visual Studio 上运行)

 1.10 应用


1.1 定义

        一种特殊的线性表,只允许在固定的一端进行插入和删除元素的操作 。进行插入和删除的一端称为栈顶,另一端称为栈底。

        栈中的元素遵循后进先出的原则。

例:若4个元素(1,2,3,4)入栈顺序为 1,2,3,4

则出栈顺序不可能为:
A. 4 3 2 1

B. 1 4 3 2

C. 3 1 4 2

D. 3 4 2 1

我们可以直接看出A选项是正确的一种出栈顺序,但是,对于其余的三个选项却感到摸不着头脑。

这是因为我们的思维受到了限制,要注意,“后进先出”不一定要所有的元素都入栈之后才能出栈,可以边进边出

下面,我们以B选项为例分析:

 故B成立!

经分析,易知,C选项错误!

1.2 创建动态数组

typedef int STDataType;
typedef struct Stack
{
	int* a;
	int top;
	int capacity;
}ST;

 1.3 栈初始化

void STInit(ST* ps) {
	assert(ps);
	ps->a = (STDataType)malloc(sizeof(STDataType) * 4);
	ps->capacity = 4;
	ps->top = 0;//栈顶元素的下一个位置
	//ps->top=-1; 栈顶元素的位置
}

 

 

1.4 栈的删除

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

1.5 向栈中插入元素(压栈)

void STPush(ST* ps, STDataType x) {
	assert(ps);
	//若需要扩容
	if (ps->top == ps->capacity) {
		if (ps == NULL) {
			perror("malloc fail");
			return;
		}
		STDataType* tmp = (STDataType*)realloc(ps->a,sizeof(STDataType) * 2);
		if (tmp == NULL) {
			perror("realloc fail");
			return;
		}
		ps->a = tmp;
		ps->capacity *= 2;
	}
	//存放数据
	ps->a[ps->top] = x;
	ps->top++;
}

1.6 从栈中删除元素(出栈)

void STPop(ST* ps) {
	assert(ps);
	assert(!STEmpty(ps));
	ps->top--;
}

1.7 判断栈是否为空

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

1.8 返回栈顶元素

STDataType STTop(ST* ps) {
	assert(ps);
	assert(!STEmpty(ps));
	return ps->a[ps->top - 1];
}

1.9 进行测试(在 Visual Studio 上运行)

头文件(Stack.h)

#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
//构建动态数组
typedef int STDataType;
typedef struct Stack
{
	int* a;
	int top;
	int capacity;
}ST;
void STInit(ST* ps);
void STPush(ST* ps, STDataType x);
void STPop(ST* ps);
int STsize(ST* ps);
bool STEmpty(ST* ps);
void STDestroy(ST* ps);
STDataType STTop(ST* ps);

源文件1(Stack.c)

#include"Stack.h"
void STInit(ST* ps) {
	assert(ps);
	if (ps == NULL) {
		perror("malloc fail");
		return;
	}
	ps->a =(STDataType*) malloc(sizeof(STDataType) * 4);
	ps->capacity = 4;
	ps->top = 0;//栈顶元素的下一个位置
	//ps->top=-1; 栈顶元素的位置
}
void STDestroy(ST* ps) {
	assert(ps);
	free(ps->a);
	ps->a = NULL;
	ps->capacity = 0;
	ps->top = 0;
}
void STPush(ST* ps, STDataType x) {
	assert(ps);
	//若需要扩容
	if (ps->top == ps->capacity) {
		if (ps == NULL) {
			perror("malloc fail");
			return;
		}
		STDataType* tmp = (STDataType*)realloc(ps->a,sizeof(STDataType) * 2);
		if (tmp == NULL) {
			perror("realloc fail");
			return;
		}
		ps->a = tmp;
		ps->capacity *= 2;
	}
	//存放数据
	ps->a[ps->top] = x;
	ps->top++;
}
void STPop(ST* ps) {
	assert(ps);
	assert(!STEmpty(ps));
	ps->top--;
}
int STsize(ST* ps) {
	assert(ps);
	return ps->top;//此时,ps->top=0(初始时top指向栈顶元素的下一个位置)
}
bool STEmpty(ST* ps) {
	assert(ps);
	return ps->top == 0;
}
STDataType STTop(ST* ps) {
	assert(ps);
	assert(!STEmpty(ps));
	return ps->a[ps->top - 1];
}

源文件2(Test.c)

#include"Stack.h"
int main() {
	ST st;
	STInit(&st);
	STPush(&st,1);
	STPush(&st,2);
	STPush(&st,3);
	STPush(&st,4);
	while (!STEmpty(&st)) {
		printf("%d ", STTop(&st));
		STPop(&st);
	}
	STDestroy(&st);
	return 0;
}

注意!栈的打印与线性表不同,由于后进先出的原则,栈在打印时,每打印一个必须将该元素出栈。

运行结果:

如果需要打印出其他结果,可以将源文件2作以修改:

#include"Stack.h"
int main() {
	ST st;
	STInit(&st);
	STPush(&st,1);
	STPush(&st,2);
	printf("%d ", STTop(&st));
	STPop(&st);
	STPush(&st,3);
	STPush(&st,4);
	printf("%d ", STTop(&st));
	STPop(&st);
	while (!STEmpty(&st)) {
		printf("%d ", STTop(&st));
		STPop(&st);
	}
	STDestroy(&st);
	return 0;
}

 可以看出,元素2和元素4边进边出。

运行结果:

 1.10 应用

习题:【数制转换】

输入一个正十进制数,输出与其等值的八进制数。

void STConversion() {
//定义栈
	ST st;
//对栈进行初始化
	STInit(&st);
//输入十进制数字N
	int N;
	scanf("%d", &N);
//将 N%8 压栈,之后将N/=8
	while (N) {
		STPush(&st, N % 8);
		N /= 8;
	}
//依次打印八进制数字
	while (!STEmpty(&st)) {
		printf("%d ", STTop(&st));
		STPop(&st);
	}
//毁栈
	STDestroy(&st);
}

运行测试:

源文件2(Test.c)

#define _CRT_SECURE_NO_WARNINGS
#include"Stack.h"
void STConversion() {
	ST st;
	STInit(&st);
	int N;
	scanf("%d", &N);
	while (N) {
		STPush(&st, N % 8);
		N /= 8;
	}
	while (!STEmpty(&st)) {
		printf("%d ", STTop(&st));
		STPop(&st);
	}
	STDestroy(&st);
}
int main() {
	STConversion();
	return 0;
}

注意!VS编译器认为scanf不安全,所以需要在文件头部添加

#define _CRT_SECURE_NO_WARNINGS

运行结果:

 

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值