栈(Stack)是编程中最常用的数据结构之一。

  栈的特点是“后进先出”,就像堆积木一样,堆的时候要一块一块堆到最上面,拆的时候需要从最上面一块一块往下拆。栈的原理也一样,只不过它的操作不叫堆和拆,而是叫入栈(或压栈)和出栈(或弹栈)。栈要求我们只能在栈顶(最上面的元素)处进行增加和删除。

  栈可以用顺序表示法(顺序栈)和链式表示法(链栈)。由于栈只需要在一端增删节点,不需要在中间某处增删节点,因此即使栈在应用中大多数做的是增删操作,顺序栈虽然在增删操作时略微逊色于链栈(因为可能会扩容),但其存储密度要高于链栈,因此二者在性能方面可以说是各有各的好处。

  下面的代码是使用 C语言 描述的链栈的代码。

  栈的头文件 Stack.h 中的代码:

/**
* 栈(链栈):
* 本程序中栈的存储方式:栈顶->节点->节点->...->栈底。即:栈顶是第一个元素
*/
#include <Constant.h> // 栈中存储的数据的类型
typedef int ElemType; // 栈中的节点的数据结构体
typedef struct StackNode {
ElemType value; // 栈节点中存储的数据的值
struct StackNode* nextNode; // 下一个节点
} StackNode; // 栈的数据结构体
typedef struct Stack {
StackNode* data; // 栈中存储的所有节点
int length; // 栈的长度
StackNode* topNode; // 栈顶元素节点
} Stack; // 初始化一个空栈
Status initStack(Stack* S) {
S->data = (StackNode*)malloc(sizeof(StackNode));
if(S->data == NULL) {
printf("初始化栈失败!\n");
return FAILURE;
}
S->length = ;
S->topNode = NULL;
return SUCCESS;
} // 销毁栈
Status destroyStack(Stack* S) {
StackNode* tmpNode;
if(S->data == NULL) {
printf("栈不存在,销毁失败!\n");
return FAILURE;
}
while(S->topNode != NULL && S->topNode != S->data) {
tmpNode = S->topNode;
S->topNode = S->topNode->nextNode;
free(tmpNode);
}
S->data = NULL;
S->length = ;
S->topNode = NULL;
return SUCCESS;
} // 清空栈
Status clearStack(Stack* S) {
StackNode* tmpNode;
if(S->data == NULL) {
printf("栈不存在,清空失败!\n");
return FAILURE;
}
if(S->topNode == NULL) {
return SUCCESS;
}
while(S->topNode != S->data) {
tmpNode = S->topNode;
S->topNode = S->topNode->nextNode;
free(tmpNode);
}
S->topNode = NULL;
S->length = ;
return SUCCESS;
} // 判断栈是否为空
Status isStackEmpty(Stack* S) {
if(S->data == NULL) {
printf("栈不存在!\n");
exit();
}
if(S->length == ) {
return TRUE;
}
return FALSE;
} // 获取栈中元素的长度
int getStackLength(Stack* S) {
if(S->data == NULL) {
printf("栈不存在!\n");
exit();
}
return S->length;
} // 查看栈顶元素的值
ElemType getTopElem(Stack* S) {
if(S->data == NULL) {
printf("栈不存在,获取元素失败!\n");
exit();
}
if(S->topNode == NULL) {
printf("栈是空栈,获取元素失败!\n");
exit();
}
return S->topNode->value;
} // 元素入栈
Status push(Stack* S, ElemType e) {
StackNode* tmpNode;
if(S->data == NULL) {
printf("栈不存在,元素入栈失败!\n");
return FAILURE;
}
tmpNode = (StackNode*)malloc(sizeof(StackNode));
if(tmpNode == NULL) {
printf("元素入栈失败!\n");
return FAILURE;
}
tmpNode->value = e;
S->length++;
if(S->topNode == NULL) {
S->topNode = tmpNode;
S->topNode->nextNode = S->data;
return SUCCESS;
}
tmpNode->nextNode = S->topNode;
S->topNode = tmpNode;
return SUCCESS;
} // 元素出栈
StackNode* pop(Stack* S) {
StackNode* tmpNode;
if(S->data == NULL) {
printf("栈不存在,元素出栈失败!\n");
exit();
}
if(S->topNode == NULL) {
printf("栈是空栈,元素出栈失败!\n");
return NULL;
}
tmpNode = S->topNode;
S->topNode = S->topNode->nextNode;
if(S->topNode == S->data) {
S->topNode = NULL;
}
tmpNode->nextNode = NULL;
S->length--;
return tmpNode;
} // 遍历栈中的元素
void traverseStack(Stack* S) {
StackNode* tmpNode;
if(S->data == NULL) {
printf("栈不存在,遍历失败!\n");
exit();
}
if(S->topNode == NULL) {
printf("栈是空栈,遍历失败!\n");
exit();
}
printf("遍历栈:");
tmpNode = S->topNode;
while(tmpNode != S->data) {
printf("%-4d", tmpNode->value);
tmpNode = tmpNode->nextNode;
}
printf("\n");
} // 栈的测试函数
int testStack() {
// 数据声明
Stack stack;
StackNode* node;
int i;
// 初始化栈
if(initStack(&stack) == SUCCESS) {
printf("初始化栈成功!\n");
}
// 判断栈是否是空栈
printf("栈是否为空栈?%s\n", isStackEmpty(&stack) == TRUE ? "是" : "否");
// 元素入栈
for(i = ; i <= ; i++) {
if(push(&stack, i) == SUCCESS) {
printf("元素%d入栈成功!\n", i);
}
}
// 遍历栈中的元素
traverseStack(&stack);
// 元素出栈
node = pop(&stack);
if(node != NULL) {
printf("元素%d成功出栈!\n", node->value);
}
// 遍历栈中的元素
traverseStack(&stack);
// 查看栈顶元素的值
printf("栈顶元素的值是:%d\n", getTopElem(&stack));
// 获取栈的长度
printf("栈的当前长度:%d\n", getStackLength(&stack));
// 清空栈
if(clearStack(&stack) == SUCCESS) {
printf("清空栈成功!\n");
}
// 销毁栈
if(destroyStack(&stack) == SUCCESS) {
printf("销毁栈成功!\n");
}
return ;
}

  常量类 Constant.h 中定义了一些常量,其代码如下:

#include <stdio.h>
#include <stdlib.h> #define TRUE 1
#define FALSE 0 #define SUCCESS 1
#define FAILURE 0 typedef int Status;

  主函数所在的文件 main.c 中的代码如下:

#include <Stack.h>

int main() {
testStack();
return ;
}

  运行结果如下:

初始化栈成功!
栈是否为空栈?是
元素1入栈成功!
元素2入栈成功!
元素3入栈成功!
元素4入栈成功!
元素5入栈成功!
遍历栈:5 4 3 2 1
元素5成功出栈!
遍历栈:4 3 2 1
栈顶元素的值是:4
栈的当前长度:4
清空栈成功!
销毁栈成功! Process returned 0 (0x0) execution time : 0.016 s
Press any key to continue.

【数据结构】之栈(C语言描述)的更多相关文章

  1. C语言学习书籍推荐《数据结构与算法分析:C语言描述(原书第2版)》下载

    维斯 (作者), 冯舜玺 (译者) <数据结构与算法分析:C语言描述(原书第2版)>内容简介:书中详细介绍了当前流行的论题和新的变化,讨论了算法设计技巧,并在研究算法的性能.效率以及对运行 ...

  2. 数据结构与抽象 Java语言描述 第4版 pdf (内含标签)

    数据结构与抽象 Java语言描述 第4版 目录 前言引言组织数据序言设计类P.1封装P.2说明方法P.2.1注释P.2.2前置条件和后置条件P.2.3断言P.3Java接口P.3.1写一个接口P.3. ...

  3. 数据结构与算法分析——C语言描述 第三章的单链表

    数据结构与算法分析--C语言描述 第三章的单链表 很基础的东西.走一遍流程.有人说学编程最简单最笨的方法就是把书上的代码敲一遍.这个我是头文件是照抄的..c源文件自己实现. list.h typede ...

  4. 最小正子序列(序列之和最小,同时满足和值要最小)(数据结构与算法分析——C语言描述第二章习题2.12第二问)

    #include "stdio.h" #include "stdlib.h" #define random(x) (rand()%x) void creat_a ...

  5. 《数据结构与算法分析——C语言描述》ADT实现(NO.00) : 链表(Linked-List)

    开始学习数据结构,使用的教材是机械工业出版社的<数据结构与算法分析——C语言描述>,计划将书中的ADT用C语言实现一遍,记录于此.下面是第一个最简单的结构——链表. 链表(Linked-L ...

  6. 《数据结构与算法分析-Java语言描述》 分享下载

    书籍信息 书名:<数据结构与算法分析-Java语言描述> 原作名:Data Structures and Algorithm Analysis in Java 作者: 韦斯 (Mark A ...

  7. 《数据结构与算法分析:C语言描述_原书第二版》CH3表、栈和队列_reading notes

    表.栈和队列是最简单和最基本的三种数据结构.基本上,每一个有意义的程序都将明晰地至少使用一种这样的数据结构,比如栈在程序中总是要间接地用到,不管你在程序中是否做了声明. 本章学习重点: 理解抽象数据类 ...

  8. 《数据结构与算法分析——C语言描述》ADT实现(NO.01) : 栈(Stack)

    这次的数据结构是一种特殊的线性表:栈(Stack) 栈的特点是后入先出(LIFO),可见的只有栈顶的一个元素. 栈在程序中的地位非常重要,其中最重要的应用就是函数的调用.每次函数调用时都会创建该函数的 ...

  9. 用链表实现栈----《数据结构与算法分析----C语言描述》

    一.头文件: #ifndef _STACK_LINK_H_ #define _STACK_LINK_H_ struct stack_record; typedef struct stack_recor ...

  10. 读书笔记:《数据结构与算法分析Java语言描述》

    目录 第 3 章 表.栈和队列 3.2 表 ADT 3.2.1 表的简单数组实现 3.2.2 简单链表 3.3 Java Collections API 中的表 3.3.1 Collection 接口 ...

随机推荐

  1. (JavaScript) 时间转为几天前、几小时前、几分钟前

    // 时间戳转多少分钟之前 getDateDiff(dateTimeStamp) { // 时间字符串转时间戳 var timestamp = new Date(dateTimeStamp).getT ...

  2. AtCoder Grand Contest 036 A-C

    目录 \(\bf A - Triangle\) \(\bf B - Do\ Not\ Duplicate\) \(\bf C - GP 2\) \(\bf D - Negative \ Cycle\) ...

  3. windows下安装nginx和基本配置

    1.下载并安装nginx 到nginx官网上下载相应的安装包,http://nginx.org/en/download.html: 下载之后进行解压,将解压后的文件放到自己心仪的目录下,如下图所示: ...

  4. 使用Rider中搭建specflow+xunit+selenium对web页面进行自动化功能测试环境

    运行rider,创建测试解决方案,选择xunit,点击create创建 ​   导入包,由于本人使用chrome浏览器(需先下载好对应的浏览器驱动),所以导入了selenium.webdriver.c ...

  5. 本地yum配置

    yum yum(Yellow dog Updater, Modified)是一个在 Fedora 和 RedHat 以及 CentOS 中的 Shell 前端软件包管理器.基于 RPM 包管理,能够从 ...

  6. MySQL InnoDB 实现高并发原理

    MySQL 原理篇 MySQL 索引机制 MySQL 体系结构及存储引擎 MySQL 语句执行过程详解 MySQL 执行计划详解 MySQL InnoDB 缓冲池 MySQL InnoDB 事务 My ...

  7. java编程思想第四版第十三章字符串 习题

    fas 第二题 package net.mindview.strings; import java.util.ArrayList; import java.util.List; /** * 无限循环 ...

  8. thinkphp在模板中使用php的函数

    thinkphp在模板中使用php的函数 使用 {:函数名} 的形式 例如: // 获取 session 中存的值 {:session('admin.loginname')} // 输出当前日期 {: ...

  9. 从壹开始 [ Design Pattern ] 之一 ║ 设计模式开篇讲

    缘起 不说其他的没用的开场白了,直接给大家分享三个小故事,都来自于我的读者粉丝(我厚着脸皮称为粉丝吧

  10. Go 语言优秀资源整理,为项目落地加速🏃

    最后更新于2019.11.22 Go 语言优秀资源整理,为项目落地加速