简单的链式表对数组的元素取反

栈是一种重要的线性结构,它是受限的线性表,是仅能在表的一端进行插入和删除运算的线性表。栈被广泛的运用到各种系统的程序设计中。
1)通常称插入、删除的一段为栈顶,另一端称为栈底。
2)当表中没有元素时称为空栈。
3)栈为后进先出的线性表,简称LIFO表。
栈的修改是按照后进先出的原则进行。每次删除的总是当前栈中最新的元素,即最后插入的元素,而最先插入的则是被放在栈的底部,要到最后才能删除。
利用数组来完成的栈是顺序表
但是我近期用得都是链表 所以还是链式栈比较好理解
代码使用的是C++语言
首先代码我们分步来完成
先是头文件

声明

//Stack.h
#pragma once
#include <iostream>
#include <conio.h>
using namespace std;
typedef int stack_element;
struct node
{
	stack_element str;

	node* next;
};
typedef struct {
	node* top;
	int num;
}stack;
void init(stack* p);

int StackEmpty(stack* sp);
void push(stack* sp, stack_element c);
stack_element pop(stack* sp);
void Show(stack* sp);

这段代码完成了对今后代码中所有函数结构体以及变量的声明。

typedef struct {
	node* top;
	int num;
}stack;

这段代码是当时从书中找到的。但是个人认为这样的写法不太好理解 所以我就换了一种写法

struct stack{
	node* top;
	int num;
};

这样的代码与上面的代码道理是一样的
结构体指针的声明还是 stack * p;
然后,置于其中的num用于计数 来确定栈的个数

初始化函数

其次,我们要对指针或者是变量进行初始化
我们放在同一个函数中

void init(stack* p)
{
	p->top = NULL;
	p->num = 0;
}

防止top是野指针,先赋值为空
接着 要保证计数变量从0开始 我们赋值为0

因此在接下来的主函数中都要记得使用这个函数来初始化变量

判断是否为空栈函数

int StackEmpty(stack* sp)
{
	return sp->top == NULL ? 1 : 0;
}

这个函数实现了对栈是否为空进行了判断
如果是空就返回真
此处利用了三目运算符

进栈函数

void push(stack* sp, stack_element c)
{
	node* np;
	np = new node;
	np->str = c;
	np->next = sp->top;
	sp->top = np;
	sp->num++;
}

形参是结构体指针和stack_element类型的值
此处是int类型
精髓:

np->next = sp->top;
	sp->top = np;

np是第一个结构体的指针 结点里的指针域指向top
让top指到结点
那么next就会指向结点
第二次 申请一个新的结点 赋值后
next处指向前面的那个结点
top指针指向新的结点
那么不断循环就形成了一个栈 这个栈的顶部指针的top处next是指向前面的一个结点的 这个地方就个链表有很大的不同
而且这样的指向对后面出栈有很大的好处
因为可以利用next来把top持续指向栈顶
当然 sp->num++;告诉栈变长了

出栈函数

stack_element pop(stack* sp)
{
	if (StackEmpty(sp))
		return 0;
	else
	{
		node* tp;
		stack_element value;
		tp = sp->top;
		value = tp->str;
		sp->top = tp->next;
		free(tp);
		sp->num--;//后来加上去的
		tp = NULL;
		return value;
	}
}

之前就判断栈是否为空
不是空栈就操作
声明一个临时指针tp
就像是我的世界中的那个tp指令一样

tp=sp->top;

把tp传送到top指针处,就是栈顶
让变量value赋值为栈顶的str;
然后top跳到下一个结点
释放栈顶的内存
因此top就又是指向栈顶的指针。
上面说的好处就是这里了 next是指向前面的,就可以保证top永远指向栈顶

遍历函数

在遍历函数这个地方发生了一个严重的错误
这个错误是在写博客 写到这个地方的时候发现的
就是遍历了一遍后这个栈变成了空栈
防止错误
就是要把栈内的所有元素都暂时放到另一个栈 遍历结束后把另一个栈放回原来的栈中
代码如下

void Show(stack* sp)
{
	stack_element sta;
	stack* po;
	po = new stack;
	for (int i = 0; i < sp->num; i++)
	{
		sta = pop(sp);
		cout << "此时的栈顶:" << sta << endl;
		push(po, sta);
	}
	for (int i = 0; i < sp->num; i++)
	{
		sta = pop(po);
		push(sp, sta);
	}
	po = NULL;
}

建立一个临时指针po
初始化po的内存之后
进入for循环 然后让变量sta接收出栈的元素 但是一旦出栈 这个栈元素就没有了
但是栈元素暂时放到了sta中 利用cout输出 再利用进栈函数把原来是栈顶的元素放到po指针指向的栈底
下一个for循环把po指针指向的栈元素取出
放到原来的栈中 让po变成空指针
防止出现野指针
原来栈顶变成栈底 两次后顺序是不变的 所以不用担心顺序的问题
以上是对所有函数的实现

接下来回归正题

数组元素的取反就是让数组的所有元素倒序

int main()
{
	int sta;
	stack* p;
	p = new stack;
	stack_element input;
	int arry[N];
	init(p);
    for (int i = 0; i < N; i++)
	{
		cin >> arry[i];
		push(p, arry[i]);
	}
	for (int i = 0; i < N; i++)
		cout << arry[i] << " ";
	cout << endl;
	for (int i = 0; i < N; i++)
		arry[i] = pop(p);


	for (int i = 0; i < N; i++)
		cout << arry[i] << " ";
		if (StackEmpty(p))
			cout << "kong";
	return 0;
}

第一个for循环先是输入数组的值
然后输出数组确保输入了
第三个就是出栈 让数组变成出栈的值
注意的是这个地方栈已经是空栈了
利用判断函数确定这个栈是空

因为上次遍历的错误的结果

这个错误让我写出了清空栈的函数
其实很简单,就是让所有元素都出来

void Delete(stack* p)
{
	for (int i = 0; i < p->num; i++)
		pop(p);
}

这些函数都能体现出计数变量的重要性
确保这个函数可以使用我现场写一段代码

int main()
{
	stack* p;
	p=new stack;
	init(p);
	push(p,123);
	if(StackEmpty())
		cout<<"空"<<endl;
	else 
		cout<<"非空"<<endl;
	Delete(p);
	if(StackEmpty())
		cout<<"空"<<endl;
	else 
		cout<<"非空"<<endl;
		return 0;
	
}

此处如果没有init(),那么就不知道num的值
所以在遍历栈的时候就不知道num的值
而且上边的代码 在出栈的时候 应该加上num–;不然只有加 没有减 那么栈的长度是不真实的。
现在我加上去了,但是刚写的时候是没有的
这些东西包括链表 都涉及内存 让人不清楚这个数值是不是真的存在
就像是栈 出栈后,值没有了。但是我刚开始没有发现。

好了好了,结束了

这就是栈

栈不像我以前写链表 这篇博客写完栈后就不会有下篇了
最后是镇店之图
亚丝娜

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值