C语言 数据结构中栈的实现代码

数据结构中的栈是什么

举一个简单的例子:在往箱子里面放衣物的时候,放在最上面的衣物总是我们最后放上去的;而当我们从箱子里取出衣物的时候,总是最先拿出上面的。这就是现实生活中的栈。

准确的讲,栈就是一种可以实现“先进后出(或者叫后进先出)”的存储结构。

学过数据结构的人都知道:栈可以用两种方式来实现,一种方法是用数组实现栈,这种栈成为静态栈;另外一种方法是用链表实现栈,这种栈叫做动态栈。

栈中通常存放着程序的局部变量等。栈通常有出栈和入栈操作。

栈的结构

空栈的结构:【其实就是栈顶和栈顶都指向一个无用的头结点】

存有结点的栈结构:【栈顶指针指向栈顶结点,栈底指针指向头结点】

栈的实现

下面是用C实现的一个栈结构的源码及详细注释:

#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
//定义结点结构体
typedef struct Node
{
 int data;  //内容
 struct Node * pNext; //指向下一结点的指针
} NODE, * PNODE;  //NODE等价于struct Node, PNODE等价于struct Node *
//定义栈的结构体
typedef struct Stack
{
 PNODE pTop;  //栈顶结点
 PNODE pBottom;  //栈底结点
} STACK, * PSTACK;  //STACK等价于struct Stack, PSTACK等价于struct Stack *
//函数声明
void initStack(PSTACK pStack);  //对栈进行初始化的函数
void pushStack(PSTACK pStack, int val); //入栈的函数
bool popStack(PSTACK pStack, int * pVal);//出栈的函数,*pVal用来保存出栈的元素内容
void traverseStack(PSTACK pStack);  //遍历栈的函数
bool isEmpty(PSTACK pStack);  //判断栈是否为空的函数
void clearStack(PSTACK pStack);  //清空栈的函数
int main(void)
{
 STACK stack;  //定义一个栈变量,STACK等价于struct Stack
 int val;  //用来保存出栈的内容
 initStack(&stack); //调用栈的初始化函数
 pushStack(&stack, 10); //调用入栈的函数
 pushStack(&stack, 20);
 pushStack(&stack, 30);
 pushStack(&stack, 50);
 traverseStack(&stack); //调用遍历栈的函数
 //调用出栈的函数
 if(popStack(&stack, &val))
 printf("出栈成功,出栈的元素值为:%d\n", val);
 else
 printf(" 出栈失败!");
 //调用清空栈的函数
 clearStack(&stack);
 traverseStack(&stack); //调用遍历栈的函数
 system("pause");
 return 0;
}

void initStack(PSTACK pStack)
{
 //创建一个空结点,让pTop指向它
 pStack->pTop = (PNODE)malloc(sizeof(NODE));
 if(NULL != pStack->pTop)
 {
 //将pBottom也指向空节点
 pStack->pBottom = pStack->pTop;
 //清空空结点的指针域
 pStack->pTop->pNext = NULL;
 }
 else   //如果内存分配失败
 {
 printf("内存分配失败!程序退出!\n");
 exit(-1);
 }
 return;
}

void pushStack(PSTACK pStack, int val)
{
 //动态创建一个新结点
 PNODE pNew = (PNODE)malloc(sizeof(NODE));
 //设置新结点的数据域的值
 pNew->data = val;
 //将新结点的指针域指向之前建的空节点
 pNew->pNext = pStack->pTop;  //pStack->pTop不能换成pStack->pBottom
 //pTop指向新的结点
 pStack->pTop = pNew;
 return;
}

bool popStack(PSTACK pStack, int * pVal)
{
 if(isEmpty(pStack))
 {
 return false;
 }
 else
 {
 //先保存栈顶元素的地址,然后将pTop指向下一元素,最后释放之前栈顶元素的内存
 PNODE rNode = pStack->pTop;
 *pVal = rNode->data;
 pStack->pTop = rNode->pNext;
 free(rNode);
 rNode = NULL;
 return true;
 }
}

void traverseStack(PSTACK pStack)
{
 //将栈顶赋给一个临时结点,因为在遍历栈的时候不能销毁栈
 PNODE pNode = pStack->pTop;
 //循环遍历栈,直到栈底
 while(pStack->pBottom != pNode )
 {
 printf("%d ", pNode->data);
 pNode = pNode->pNext;
 }
 printf("\n");
 return;
}

bool isEmpty(PSTACK pStack)
{
 if(pStack->pTop == pStack->pBottom)
 return true;
 else
 return false;
}

void clearStack(PSTACK pStack)
{ //栈为空,则退出该函数
 if(isEmpty(pStack))
 {
 return;
 }
 else
 {
 //两个结点指针变量用来释放栈中元素的内存
 PNODE p = pStack->pTop;
 PNODE q = NULL;
 //循环释放内存
 while(p != pStack->pBottom)
 {
  q = p->pNext;
  free(p);
  p = q;
 }
 //将栈顶和栈底指向同一个指针域为空的结点
 pStack->pTop = pStack->pBottom;
 return;
 }
}

栈的典型应用

生产消费模型常用栈来实现。生产者生产的东西都放入栈中,然后消费者从栈中依次取出东西,当栈顶和栈底指向都指向首结点时,生产的东西就被消耗光了。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

(0)

相关推荐

  • C语言数据结构 栈的基础操作

    C语言数据结构 栈的基础操作 实现了栈的基本操作,包括入栈出栈,以及书上没有写的销毁栈等操作,并对代码进行了详细的注释 MyStack.h /* * Include.h * * Created on: 2016.11.23 * Author: Jack Cui */ #ifndef MYSTACK_H_ #define MYSTACK_H_ #include <stdlib.h> #include <stdio.h> #include <malloc.h> /*栈(St

  • C语言数据结构之栈简单操作

    C语言数据结构之栈简单操作 实验: 编写一个程序实现顺序栈的各种基本运算,并在此基础上设计一个主程序,完成如下功能: (1)初始化顺序栈 (2)插入元素 (3)删除栈顶元素 (4)取栈顶元素 (5)遍历顺序栈 (6)置空顺序栈 分析: 栈的顺序存储结构简称为顺序栈,它是运算受限的顺序表. 对于顺序栈,入栈时,首先判断栈是否为满,栈满的条件为:p->top= =MAXNUM-1,栈满时,不能入栈; 否则出现空间溢出,引起错误,这种现象称为上溢. 出栈和读栈顶元素操作,先判栈是否为空,为空时不能操作

  • C语言 数据结构中栈的实现代码

    数据结构中的栈是什么 举一个简单的例子:在往箱子里面放衣物的时候,放在最上面的衣物总是我们最后放上去的:而当我们从箱子里取出衣物的时候,总是最先拿出上面的.这就是现实生活中的栈. 准确的讲,栈就是一种可以实现"先进后出(或者叫后进先出)"的存储结构. 学过数据结构的人都知道:栈可以用两种方式来实现,一种方法是用数组实现栈,这种栈成为静态栈:另外一种方法是用链表实现栈,这种栈叫做动态栈. 栈中通常存放着程序的局部变量等.栈通常有出栈和入栈操作. 栈的结构 空栈的结构:[其实就是栈顶和栈顶

  • C语言数据结构中数制转换实例代码

    C语言数据结构中数制转换实例代码 数制转换是严蔚敏的数据结构那本书中的例子,但是那本书中的例子大都是用伪代码的形式写的,不是很容易理解和实现,对初学者造成了不小的困扰,在这里我们将其详尽的实现出来,以便初学者调试和运行,并从中有所收获. #include <stdlib.h> #include <stdio.h> #include<malloc.h> #define STACK_INIT_SIZE 10 //定义最初申请的内存的大小 #define STACK_INCR

  • C语言数据结构中约瑟夫环问题探究

    目录 问题描述 基本要求 测试数据 实现思路1 实现思路2 结果 数据结构开讲啦!!! 本专栏包括: 抽象数据类型 线性表及其应用 栈和队列及其应用 串及其应用 数组和广义表 树.图及其应用 存储管理.查找和排序 将从简单的抽象数据类型出发,深入浅出地讲解复数 到第二讲线性表及其应用中会讲解,运动会分数统计,约瑟夫环,集合的并.交和差运算,一元稀疏多项式计算器 到最后一步一步学会利用数据结构和算法知识独立完成校园导航咨询的程序. 希望我们在学习的过程中一起见证彼此的成长. 问题描述 约瑟夫环问题

  • C语言数据结构中二分查找递归非递归实现并分析

    C语言数据结构中二分查找递归非递归实现并分析 前言: 二分查找在有序数列的查找过程中算法复杂度低,并且效率很高.因此较为受我们追捧.其实二分查找算法,是一个很经典的算法.但是呢,又容易写错.因为总是考虑不全边界问题. 用非递归简单分析一下,在编写过程中,如果编写的是以下的代码: #include<iostream> #include<assert.h> using namespace std; int binaty_search(int* arr, size_t n, int x)

  • C语言 数据结构中求解迷宫问题实现方法

    C语言 数据结构中求解迷宫问题实现方法 在学习数据结构栈的这一节遇到了求迷宫这个问题,拿来分享一下~ 首先求迷宫问题通常用的是"穷举求解" 即从入口出发,顺某一方向试探,若能走通,则继续往前走,否则原路返回,换另一个方向继续试探,直至走出去. 我们可以先建立一个8*8的迷宫其中最外侧为1的是墙 int mg[M+2][N+2]={ {1,1,1,1,1,1,1,1,1,1}, {1,0,0,1,0,0,0,1,0,1}, {1,0,0,1,0,0,0,1,0,1}, {1,0,0,0,

  • javascript数据结构中栈的应用之符号平衡问题

    本文实例讲述了javascript数据结构中栈的应用之符号平衡问题.分享给大家供大家参考,具体如下: 由于栈先进后出的结构,我们可以将其作为有用的工具,下面就介绍一下栈的应用. 首先是符号的平衡问题.有一串字符串,我们需要判断其中固定的字符是否成对出现,比如<> {} [] () 等.当然实现的方法有很多,但是采用栈的实现会相对更加简单. 实现上述算法的JavaScript代码如下 <!DOCTYPE html> <html> <head> <meta

  • JavaScript数据结构中栈的应用之表达式求值问题详解

    本文实例讲述了JavaScript数据结构中栈的应用之表达式求值问题.分享给大家供大家参考,具体如下: 下面来谈一个比较经典的表达式求值问题,这个问题主要是设计到操作符的优先级.我们通常看到的表达式都是中缀表达式,存在很多优先级差别,而后缀表达式则没有这些优先级问题.下面先看看两种表达式的区别. 中缀表达式:a*b+c*d-e/f      后缀表达式:ab*cd*+ef/- 从中缀表达式转换到后缀表示式是很难实现的,我们这里可以通过栈的思想来实现.下面进行详细的介绍是什么样的思想: 在对一个中

  • C语言数据结构中堆排序的分析总结

    目录 一.本章重点 二.堆 2.1堆的介绍(三点) 2.2向上调整 2.3向下调整 2.4建堆(两种方式) 三.堆排序 一.本章重点 堆 向上调整 向下调整 堆排序 二.堆 2.1堆的介绍(三点) 1.物理结构是数组 2.逻辑结构是完全二叉树 3.大堆:所有的父亲节点都大于等于孩子节点,小堆:所有的父亲节点都小于等于孩子节点. 2.2向上调整 概念:有一个小/大堆,在数组最后插入一个元素,通过向上调整,使得该堆还是小/大堆. 使用条件:数组前n-1个元素构成一个堆. 以大堆为例: 逻辑实现: 将

  • C语言数据结构中树与森林专项详解

    目录 树的存储结构 树的逻辑结构 双亲表示法(顺序存储) 孩字表示法(顺序+链式存储) 孩子兄弟表示法(链式存储) 森林 树的遍历 树的先根遍历(深度优先遍历) 树的后根遍历(树的深度优先遍历) 树的层序遍历(广度优先遍历) 森林的遍历 先序遍历森林 中序遍历森林 树的存储结构 树的逻辑结构 树是n(n≥0)个结点的有限集合,n=0时,称为空树,这是一种特殊情况.在任意--棵非空树中应满足: 1)有且仅有一个特定的称为根的结点. 2)当n>1时,其余结点可分为m(m>0)个互不相交的有限集合T

  • java 数据结构中栈和队列的实例详解

    java 数据结构中栈和队列的实例详解 栈和队列是两种重要的线性数据结构,都是在一个特定的范围的存储单元中的存储数据.与线性表相比,它们的插入和删除操作收到更多的约束和限定,又被称为限定性的线性表结构.栈是先进后出FILO,队列是先进先出FIFO,但是有的数据结构按照一定的条件排队数据的队列,这时候的队列属于特殊队列,不一定按照上面的原则. 实现栈:采用数组和链表两种方法来实现栈 链表方法: package com.cl.content01; /* * 使用链表来实现栈 */ public cl

随机推荐