【数据结构取经之路】栈

目录

引言

栈的性质

顺序栈 

栈的基本操作 

初始化 

销毁

插入

删除

判空

取栈顶元素

栈的大小

完整代码: 


引言

栈(stack),可以用数组实现,也可以用链表实现。用数组实现的栈叫顺序栈,用链表实现的栈叫链式栈,本文讲解的是顺序栈。栈,作为一种特殊的数据结构,在一些方面有着重要用途,例如,快速排序的非递归实现就需要借助栈来完成。

栈的性质

栈是限定仅在栈顶进行插入或删除操作的线性表。它是遵循“后进先出”的原则的,队列正好与之相反。

顺序栈 

 底层用数组实现,当数组空间不够用时就扩容。这些操作和用数组来实现通讯录如出一辙,想必大家已轻车熟路,这里就点到为止了。

栈的基本操作 

因为顺序栈的底层是用数组实现,所以本质上还是在操作数组。

初始化 

初始化操作一般有两种,第一种,在初始化时就给数组分配一定的空间,第二种,初始化时不给分配空间,第一次插入数据时才个数组分配空间。这两种方法用哪一种都无可厚非,按自己喜好来就好,这里呢我就偏爱第二种方法。

代码:

typedef int StackDataType;

typedef struct Stack
{
	StackDataType* a;
	int capacity;//容量
	int top;
}Stack;
void StackInit(Stack* pst)
{
    assert(pst);
	pst->a = NULL;
	pst->capacity = 0;//容量
	pst->top = 0;
}

 需要注意的一个细节是,top指向的是栈顶元素的下一个,以防返回栈顶元素时出现错误。细心观察也会发现,top的值就是栈中的元素个数,这样,返回栈的大小就简单了。

销毁

因为底层使用数组实现,所以要释放数组空间只需要free一把就行了。

void StackDestroy(Stack* pst)
{
	assert(pst);
	pst->capacity = 0;
	pst->top = 0;
	free(pst->a);
}

插入

底层用数组实现,那么在插入时就有可能面临着空间不够的问题,所以在插入之前,需要判断数组是否已满。

代码:

void StackPush(Stack* pst, StackDataType x)
{
	assert(pst);
	if (pst->capacity == pst->top)
	{
		int newCapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
		StackDataType* tmp = (StackDataType*)realloc(pst->a, sizeof(StackDataType) * newCapacity);
		if (tmp == NULL)
		{
			perror("malloc fail");
			return;
		}
        pst->a = tmp;
	}

	pst->a[pst->top] = x;
	pst->top++;
}

删除

顺序栈的删除实际上就是数组最后一个元素的删除,不需要挪动数据,top--即可,这样即使数组中还存在该元素,但是已经访问不到了。

代码:

void StackPop(Stack* pst)
{
	assert(pst);
	pst->top--;
}

判空

空的特征是:top为0,所以只需要判断top是否为0即可。

代码:

bool StackEmtpy(Stack* pst)
{
	assert(pst);
	return pst->top == 0;
}

取栈顶元素

栈顶元素的下标为top-1,返回该下标对应的值即可。

代码:

StackDataType StackTop(Stack* pst)
{
	assert(pst);
	return pst->a[pst->top - 1];
}

虽然简单,但请不要写成pst->a[pst->top--]. 后置--是有副作用的,也就是说会改变top的值,但这里不需要改变top的值。当然,这种错误是极小概率事件,只是顺便提一提。

栈的大小

top的值就是栈的大小,所以返回top即可。

代码:

int StackSize(Stack* pst)
{
	assert(pst);
	return pst->top;
}

完整代码: 


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


typedef int StackDataType;

typedef struct Stack
{
	StackDataType* a;
	int capacity;//容量
	int top;
}Stack;

void StackInit(Stack* pst);

void StackDestroy(Stack* pst);

void StackPush(Stack* pst, StackDataType x);

void StackPop(Stack* pst);

bool StackEmtpy(Stack* pst);

StackDataType StackTop(Stack* pst);

int StackSize(Stack* pst);


void StackInit(Stack* pst)
{
	assert(pst);

	pst->a = NULL;
	pst->capacity = 0;
	pst->top = 0;
}

void StackDestroy(Stack* pst)
{
	assert(pst);
	pst->capacity = 0;
	pst->top = 0;
	free(pst->a);
}

void StackPush(Stack* pst, StackDataType x)
{
	assert(pst);
	if (pst->capacity == pst->top)
	{
		int newCapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
		StackDataType* tmp = (StackDataType*)realloc(pst->a, sizeof(StackDataType) * newCapacity);
		if (tmp == NULL)
		{
			perror("malloc fail");
			return;
		}

		pst->a = tmp;
	}

	pst->a[pst->top] = x;
	pst->top++;
}


void StackPop(Stack* pst)
{
	assert(pst);
	pst->top--;
}


bool StackEmtpy(Stack* pst)
{
	assert(pst);
	return pst->top == 0;
}


StackDataType StackTop(Stack* pst)
{
	assert(pst);
	return pst->a[pst->top - 1];
}

int StackSize(Stack* pst)
{
	assert(pst);
	return pst->top;
}

 

 

  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
作为华为OD机试题,西天取经是一道经典的题目,涉及到许多方面的考察和思考。西天取经是《西游记》中的故事情节,其中主要任务是取得真经,以拯救世界。而作为华为的工程师,我们需要先了解这个挑战的背景和目标。 西天取经考验的是团队协作和个人能力。首先,我们需要有一个有冒险精神和毅力的团队,由团队领导者牵头组织。团队成员需要各司其职,需要有地理学家、历史学家、语言学家、武术高手等各个领域的专家。他们应该紧密协作,共同解决困难和挑战。 其次,团队需要经历训练,提高个人能力。这个过程需要不断学习、研究和实践。地理学家需要了解西方地理环境和地形,历史学家需要研究西方历史和文化,语言学家需要掌握西方语言,武术高手需要提升自己的武术技巧。通过不断提高个人能力,团队成员才能够应对各种困难和挑战。 在西天取经的过程中,我们需要面对各种风险和困难。对于华为的工程师来说,我们需要明确目标并制定详细的计划,同时需要从容应对各种变化和挑战。团队成员需要保持平静、乐观,并积极寻找解决问题的方法和策略。 最后,成功取得真经需要付出巨大的努力和付出。这需要团队成员展现出坚持不懈的毅力和决心。即使在挫折面前,我们也不能轻易放弃,而应该鼓励自己不断尝试、进步,并互相鼓励和支持。 总的来说,西天取经不仅考验个人能力,更是一个团队合作的过程。只有通过团队成员的共同努力和协作,我们才能够成功地完成任务,取得真经,为世界带来积极的影响。华为作为全球知名的科技企业,注重团队合作和个人能力的培养,相信我们的工程师能够在西天取经的过程中取得成功。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值