数据结构:顺序栈的实现

1.顺序栈的简介

1.1顺序栈的结构

  顺序栈一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈的实现一般可以用数组或者链表实现,相对于数组的结构实现更优一些。因为数组在尾部插入如的数据代价比较小。

1.2顺序栈的特征

  顺序栈的底层实现储存数据的工具为数组,基本访问方式通过栈顶指针来对数据进行查找。栈中的数据遵循后进先出即LIFO(Last In First Out)的原则,即入数据在栈顶,出数据也在栈顶,对于顺序栈来说,栈顶就是数组的尾部,引起独特的数据处理方式导致了一些不便,比如无法直接访问数组中间的某个值,只能顺序访问。

2.顺序栈的实现

  顺序表实现的结构体中包括自定义类型的数组(根据个人需求),两个整形变量,一个用来记录栈顶的位置,另一个用来记录整个数组的大小,因其用数组来出储存数据可能有数组大小不足的情况,这时候就要在堆区动态内存开辟空间,这也是为什么要有两个整型变量的原因之一,第一个整形可以理解为数组中有效数据的多少,另一个则是整个数组的大小,则第一个整形是小于或等于第二个整形的。

2.1Stack.h

  这是Stack.h中包含的头文件

#pragma once

#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>

下面是对顺序表的定义

    其中对int的重命名是为了以后可以根据自己需求修改数据类型方便。

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

下面是顺序表实现功能函数的接口

  顺序表可以实现顺序表的初始化,销毁,入栈,出栈,取栈顶数据,判断栈是否为空,测栈的数据多少的基本功能。

void STInit(ST* ps);
void STDestroy(ST* ps);
void STPush(ST* ps, STDataType x);
void STPop(ST* ps);
STDataType STTop(ST* ps);
bool STEmpty(ST* ps);
int STSize(ST* ps);

2.2Stack.c

栈的初始化

// 定义一个函数 STInit,用于初始化结构体 ST 中的成员变量
void STInit(ST* ps)
{
	// 断言:ps 指针不为空
	assert(ps);
	// 将结构体 ST 中的成员变量 a 初始化为 NULL
	ps->a = NULL;
	// 将结构体 ST 中的成员变量 top 初始化为 0
	ps->top = 0;
	// 将结构体 ST 中的成员变量 capacity 初始化为 0
	ps->capacity = 0;
}

 栈的销毁

// 销毁ST结构体
void STDestroy(ST* ps)
{
	// 断言:ps不为空
	assert(ps);
	// 释放ps指向的动态数组内存
	free(ps->a);
	// 将ps指向的动态数组指针置空
	ps->a = NULL;
	// 将ps的top和capacity置空
	ps->top = ps->capacity = 0;
}

 入栈

// 向栈中添加元素
void STPush(ST* ps, STDataType x)
{
	// 断言,确保ps不为空
	assert(ps);
	// 如果栈满,则扩容
	if (ps->capacity == ps->top)
	{
		// 如果栈容量为0,则初始化为4,否则扩容为原来的2倍
		ps->capacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		// 扩容
		ps->a = (STDataType*)realloc(ps->a, ps->capacity * sizeof(STDataType));
		// 如果扩容失败,则打印错误信息,并退出
		if (!ps->a)
		{
			printf("realloc fail\n");
			
			exit(-1);
		}
	}
	// 向栈中添加元素
	ps->a[ps->top++] = x;
}

 出栈

void STPop(ST* ps)
{
	// 断言:ps不为空
	assert(ps);
	// 断言:栈不为空
	assert(!STEmpty(ps));
	// 栈顶指针减1
	ps->top--;
}

 获取栈顶元素

// 用于获取栈顶元素
STDataType STTop(ST* ps)
{
	// 断言ps不为空
	assert(ps);
	// 断言栈不为空
	assert(!STEmpty(ps));
	// 返回栈顶元素
	return ps->a[ps->top - 1];
}

 判断栈是否为空

// 判断栈是否为空
bool STEmpty(ST* ps)
{
	assert(ps); // 断言栈不为空
	return ps->top == 0; // 如果栈顶元素为0,则栈为空
}

 获取栈的大小

// 获取栈的大小
int STSize(ST* ps)
{
	// 断言:栈不为空
	assert(ps);
	// 返回栈的大小
	return ps->top;
}

 2.3Test.c

​
#include"Stack.h"

int main()
{
    // 定义一个栈结构体变量s
    ST s;
    // 初始化栈s
    STInit(&s);
    // 将元素压入栈s
    STPush(&s, 1);
    STPush(&s, 2);
    STPush(&s, 3);
    STPush(&s, 4);
    STPush(&s, 5);
    // 如果栈不为空,则循环
    while (!STEmpty(&s))
    {
        // 获取栈顶元素
        int top = STTop(&s);
        // 输出栈顶元素
        printf("top = %d\n", top);
        // 弹出栈顶元素
        STPop(&s);
    }
    // 销毁栈s
    STDestroy(&s);
    return 0;
}

​

  但此时应注意栈的出栈顺序应是相对的,比如给出以下代码:

#include"Stack.h"

int main()
{
    // 定义一个栈结构体变量s
    ST s;
    // 初始化栈s
    STInit(&s);
    // 将元素压入栈s
    STPush(&s, 1);
    STPush(&s, 2);
    STPush(&s, 3);
    // 获取栈顶元素
    int top = STTop(&s);
    // 输出栈顶元素
    printf("top = %d\n", top);
    // 弹出栈顶元素
    STPop(&s);
    STPush(&s, 4);
    STPush(&s, 5);
    // 如果栈不为空,则循环
    while (!STEmpty(&s))
    {
        // 获取栈顶元素
        int top = STTop(&s);
        // 输出栈顶元素
        printf("top = %d\n", top);
        // 弹出栈顶元素
        STPop(&s);
    }
    // 销毁栈s
    STDestroy(&s);
    return 0;
}

  其运行结果如所示,在还未把4,5压入栈中的时候先让3出栈,这时候不管4,5的顺序,3是相对于2,1先出栈的。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值