ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

栈(stack) C语言实现 详解

2022-07-13 22:02:29  阅读:202  来源: 互联网

标签:Status SeqStack return int C语言 public 详解 next stack


将颠倒的Push和Pop方法更正,并更换图片。
栈是数据结构中较为简单的结构体,是一种操作收到限制的线性表.但简单不代表没用,毕竟数组很简单.但谁敢说数组没用呢?


栈的理论
栈是一个先进后出的结构,类似于堆盘子,先放到地上的盘子最后被取走(默认只能取走一个盘子)
栈其实就是操作受限的线性表,只有一个口,每一次操作时,这个口可以当出口也可以当入口.
例如:水桶,注入水时,水桶的头当做入口,倒水时,水桶的头当做出口
栈的图解.
在图解之前,先举一个例子,让大家记住栈 : 栈其实就是吃了一顿饭,然后吐出来.

这是一个空栈,只有上面是入口和出口


放入一个元素a

 

接着依次放入B,C元素


取出一个元素,由栈只有一个口的特点可以知道取出了C


再次放入一个元素D


栈的可用操作

根据理论环节,可以轻易的看出:栈的基本操作只有两个:

入栈
出栈
而且样子长得十分像一个水桶。

但是如果栈已经放满了,就像水桶装满了水一样,不能再放水了,即不能再进行入栈操作,所以要在每次入栈前判断栈满的情况.同理,出栈之前,栈中必须有数据,不然就出现要么空指针,要么野指针.都不是我们想要的结果,所以出栈前要判断栈空,.
所有一个栈一共有四个功能:

入栈(英文名:push)
判(栈)满(isFull)
出栈(pop)
判(栈)空(isEmpty)
栈的C语言定义(结构体)
开篇就说了栈是操作收到限制的线性表,而众所周知的线性表主要有:
1.顺序存储的数组,
优点: 节省空间, 操作简单,学习成本较低,易于理解.
缺点: 栈的大小一开始就声明’死’了,不利于使用.
2.非顺序存储的链表.
优缺点:与数组栈正好相反.

两种栈各有好处,争论是愚蠢的,学习是学不完的,所以赶快开始coding吧

数组栈
数组栈,顾名思义,就是基于数组的栈,也是说把一个数组的强大的下标功能阉割掉,并且只能从一头进入(数组头明显更为方便)
所以结构体为:
(为了方便学习,存储类型统一使用int,但是我们一般更习惯在头文件下面给int 起一个别名,原因很简单:这样就这样实现简单的多态,需要将int类型栈改成char类型栈时,只需要改定义的别名中的类型即可)

typedef struct
{
int Data[MaxSize]; // 存储元素的数组
int topIdx; //栈顶指针
}SeqStack;
1
2
3
4
5
栈的四个基本操作定义:

//return 0 为false,1为true(下同)
// 将元素推入栈中
int Push(SeqStack &L, int e)
{ // 栈已满
if(L.topIdx==MaxSize -1)
{
return 0;
}
// 加入栈中
L.Data[L.topIdx++] = e;
// 返回自身
return e;
}
// 移除栈顶元素
int Pop(SeqStack &L)
{ // 栈空
if(L.topIdx == 0)
{
//返回失败
return 0;
}
// 打印并返回栈
int val = L.Data[--L.topIdx];
printf("%d ",val);
return val;
}
//判断栈s是否为空
int isEmpty(SeqStack s)
{
// 如果下标在0,说明栈中无元素
if(s.topIdx != 0)
{
return 1;
}
return 0;
}
// 判断栈是否已栈.
Status isFull(SeqStack s)
{
// 已满返回true(1)
if(s.topIdx != MaxSize -1)//之前的定义数组的最大值的下标
{
return 1;
}
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
链表栈
结构体

typedef struct LNode
{
ElemType data;
struct LNode * next;
} LNode,*LinkList;
1
2
3
4
5
两大功能(链表无需判满,判空也简单,不再单独实现)

Status Pop(LinkList L)
{
if(L->next == NULL)
{
return 0;
}
LinkList tem = L->next;
printf("%d ",tem->data);
L->next = tem->next;
free(tem);
return 1;
}
Status Push(LinkList L, ElemType e)
{
LinkList newNode = (LinkList) malloc(sizeof(LinkList));
newNode->data = e;
newNode->next = L->next;
L->next = newNode;
return 1;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
最后写几个简单的作业(我们老师留给我们的)以及我的代码

//1、本题要求实现顺序栈,写出Push 、Pop、StackEmpty函数的实现,并用一个简单的main函数测试。

//已有类型定义
typedef struct
{
ElementType Data[MaxSize]; // 存储元素的数组
Position Top; //栈顶指针
}SeqStack;

//函数接口定义:
Status Push(SeqStack &L, ElemType e);
Status Pop(SeqStack &L, ElemType &e);
Status StackEmpty(SeqStack s); //判断栈s是否为空
//其中 L 和 e 都是用户传入的参数。 L 是带头结点的头指针; e 是数据元素。
/**
* 3、进制转换。
* 输入一个十进制正整数n和一个目标进制R(1<R<10),将n转换为R进制。要求不使用递归或数组,而使用第1题* 或第2题中定义的栈来实现。
*/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
我的代码实现:

#include <stdio.h>
#include <stdlib.h>
#define MaxSize 100
typedef int Status;
typedef int ElemType;
typedef int Position;
//1、本题要求实现顺序栈,写出Push 、Pop、StackEmpty函数的实现,并用一个简单的main函数测试。
//已有类型定义
typedef struct
{
ElemType Data[MaxSize]; // 存储元素的数组
Position Top; //栈顶指针
} SeqStack;

//函数接口定义:
Status Push(SeqStack &L,ElemType e);
Status Pop(SeqStack &L);
Status StackEmpty(SeqStack s); //判断栈s是否为空
Status prinStack(SeqStack &L);
Status convNum(int n, int R);
Status pipei();
void work1();
//其中 L 和 e 都是用户传入的参数。 L 是带头结点的头指针; e 是数据元素。
int main()
{
//work1();//第一题
//convNum(8,2);//进制转化
pipei();
return 0;
}
Status prinStack(SeqStack &L)
{
while (StackEmpty(L))
{
Push(L);
}
return 1;
}
void work1()
{
SeqStack L;
L.Top = 0;
Pop(L, 1);
Pop(L, 2);
Pop(L, 3);
prinStack(L);
}
Status Pop(SeqStack &L)
{
if(L.Top == 0)
{
return 0;
}
printf("%d ",L.Data[--L.Top]);
return 1;
}
Status Push(SeqStack &L, ElemType e)
{
if(L.Top==MaxSize -1)
{
return 0;
}
L.Data[L.Top++] = e;
return 1;
}
//判断栈s是否为空
Status StackEmpty(SeqStack s)
{
if(s.Top != 0)
{
return 1;
}
return 0;
}
//3、进制转换。
//输入一个十进制正整数n和一个目标进制R(1<R<10),将n转换为R进制。要求不使用递归或数组,而使用第1题或第2题中定义的栈来实现。
Status convNum(int n, int R)
{
//声明栈
SeqStack L;
L.Top = 0;
while (n!=0)
{
//将每次产生的余数防入栈低
Pop(L, n%R);
n/=R;
}
prinStack(L);
return 1;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
以下附上Java 代码实现的栈

public class LinkedStack<T> {
private Node topNode;

public T push(T newEntry) {
Node newNode = new Node<T>(newEntry, topNode);
topNode = newNode;
T tempData = peek();
return tempData;
}

public T pop() {
T tempData = peek();
if (tempData == null) {
return null;
}
topNode = topNode.next;
return tempData;
}

public T peek() {
if (isEmpty()) {
return null;
}
return (T) topNode.data;
}

public boolean isEmpty() {
return topNode == null;
}

public void clear() {
topNode = null;
// java拥有内存回收,只需要让头结点引用为空即可,GC就可以回收掉所有其他节点。
}

public LinkedStack() {
this.topNode = null;
}

private class Node<T> {
private T data;
private Node next;

public Node(T dataPortion) {
this(dataPortion, null);
}

public Node(T data, Node next) {
super();
this.data = data;
this.next = next;
}

public T getData() {
return data;
}

public void setData(T data) {
this.data = data;
}

public Node getNext() {
return next;
}

public void setNext(Node next) {
this.next = next;
}

}
}
————————————————
版权声明:本文为CSDN博主「过道」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/m0_37961948/article/details/80245008

搜索

复制

标签:Status,SeqStack,return,int,C语言,public,详解,next,stack
来源: https://www.cnblogs.com/stdxxd/p/16475707.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有