栈(链式栈)----C语言

链式栈:就是一种操作受限的单向链表,对单向链表还不了解的可先看一下之前的一篇关于单向链表的随笔,链表(单向链表的建立、删除、插入、打印),理解了单向链表后再来看链式栈就比较轻松了
链式栈的操作一般含有:出栈、入栈、栈的初始化、判断栈是否为空、清空栈,下面先上声明部分代码
#include <stdio.h>
#include <stdlib.h>
#define Empty 0 /* 栈空 */
#define Avail 1 /* 栈可用 */ typedef struct SNode
{
int data;
struct SNode *next;
}StackNode;
typedef struct LStack
{
StackNode *top; /* 栈顶指针 */
StackNode *bottom; /* 栈底指针 */
int height; /* 链式栈高度 */
}LinkStack; LinkStack InitStack (LinkStack pStack); /* 栈顶指针、栈底指针、栈高度初始化*/
LinkStack Push (LinkStack pStack); /* 入栈 */
LinkStack Pop (LinkStack pStack); /* 出栈 */
int StackEmpty (LinkStack pStack); /* 判断栈是否为空 */
LinkStack DeletStack (LinkStack pStack);/* 清空栈 */
void DisplyStack (LinkStack pStack); /* 遍历栈----自顶至底*/
一、节点的声明
typedef struct SNode
{
int data;
struct SNode *next;
}StackNode;
链式栈节点的声明与单向链表的声明相同,都是由数据域和指针域组成,这里不再赘述
二、栈顶、栈底、栈高度的声明
typedef struct LStack
{
StackNode *top; /* 栈顶指针 */
StackNode *bottom; /* 栈底指针 */
int height; /* 链式栈高度 */
}LinkStack;
三、函数声明
LinkStack InitStack (LinkStack pStack); /* 栈顶指针、栈底指针、栈高度初始化*/
LinkStack Push (LinkStack pStack); /* 入栈 */
LinkStack Pop (LinkStack pStack); /* 出栈 */
int StackEmpty (LinkStack pStack); /* 判断栈是否为空 */
LinkStack DeletStack (LinkStack pStack);/* 清空栈 */
void DisplyStack (LinkStack pStack); /* 遍历栈----自顶至底*/
链式栈和单向链表的区别
上面已经提到的是链式栈是一种操作受限的单向链表(废话··),先来回顾一下单向链表的建立过程(不清楚单向链表的可以先之前的另一篇随笔链表(单向链表的建立、删除、插入、打印)),单向链表在添加新的节点的时候是将原链表最后一个节点的
指针域指向新建的节点,然后新建节点指针域置为NULL作为链表的最后一个节点,而链式栈在添加新的节点的时候操作就不太一样了,先来分析下栈的操作,栈只是栈顶来做插入和删除操作,那么栈顶放在链表的头部还是尾部呢?由于单向链表有头指针
而栈顶指针也是必须的,那么就把栈顶指针当作头指针来使用,比较好的办法是把栈顶放到单链表的头部。另外栈顶在头部了,那么单链表的头结点也就失去了意义,通常对于链式栈来说,是不需要头结点的,现在来说链式栈添加新节点的操作
链式栈:新一个节点->将新建节点的指针域指向原栈顶节点->将栈顶指针移动到新建节点
单向链表:新建一个节点->将原链表最后的一个节点的指针域指向新建节点->新建节点的指针域置为NULL作为新链表的最后一个节点
为了方便读者更加直观了解这个过程下面上图:


链式栈操作部分
一、入栈
/* Function: 入栈 */
LinkStack Push (LinkStack pStack)
{
int data;
StackNode *temp; if ((temp = (StackNode *)malloc(sizeof(StackNode))) == NULL)
{
printf("内存空间不足\n");
return pStack;
}
if (StackEmpty(pStack) == Empty) /* 如果栈为空 */
{
pStack.top = pStack.bottom = temp; /* 栈顶、栈底指针都指向新建节点 */
temp->next = NULL; /* 节点指针域为空 */
printf("Please input data");
scanf("%d", &data);
pStack.top->data = data;
pStack.height++; return pStack;
}
else /* 栈不为空 */
{
temp->next = pStack.top;/* 新建节点指向原来的栈顶 */
pStack.top = temp; /* 栈顶指针指向新建节点 */
printf("Please input data");
scanf("%d", &data);
pStack.top->data = data;
pStack.height++; return pStack;
}
}
二、出栈
/* Function: 出栈 */
LinkStack Pop (LinkStack pStack)
{
StackNode *Second; if (StackEmpty(pStack) == Empty) /* 判断栈是否为空 */
{
printf("栈为空,无法出栈\n");
return pStack;
}
if (pStack.top == pStack.bottom) /* 如果出栈的元素为最后一个元素 */
{
printf("出栈元素为%d\n", pStack.top->data);
free(pStack.top);
pStack.top = pStack.bottom = NULL; /* 栈顶、栈底都指针都置为空 */
pStack.height--; return pStack;
}
printf("出栈元素为%d\n", pStack.top->data);
Second = pStack.top->next; /* 指向栈顶的前一个元素*/ free(pStack.top); /* 释放栈顶节点 */
pStack.top = Second;/* 将头指针移动到新的栈顶节点 */
pStack.height--; return pStack;
}
出栈时需要判断三种情况,第一种情况:栈为空、第二种情况:栈中只有一个元素、第三种情况:栈中元素大于等于两个
三、判断栈是否为空
/* Function: 判断栈是否为空 */
int StackEmpty (LinkStack pStack)
{
if (pStack.top == NULL && pStack.bottom == NULL)
{
return Empty;
}
else
{
return Avail;
}
}
四、遍历栈
/* Function: 遍历栈 自顶到底*/
void DisplyStack (LinkStack pStack)
{
if (StackEmpty(pStack) == Empty)
{
printf("栈为空,无法遍历\n");
return ;
}
printf("栈中元素[");
while (pStack.top != NULL)
{
printf("%d->", pStack.top->data);
pStack.top = pStack.top->next;
}
printf("]\n");
}
五、清空栈
/* Function: 清空栈 */
LinkStack DeletStack (LinkStack pStack)
{
StackNode *del; while (pStack.top != NULL)
{
del = pStack.top->next; /* 栈顶节点的前一个节点 */
free(pStack.top); /* 释放节点 */
pStack.top = del; /* 栈顶指针移动到新栈顶 */
} return pStack;
}
六、初始化栈顶、栈底指针和栈高度
/* Function: 初始化栈顶、栈底、栈高度*/
LinkStack InitStack (LinkStack pStack)
{
pStack.top = pStack.bottom = NULL;
pStack.height = ; return pStack;
}
链式栈实现完整代码
#include <stdio.h>
#include <stdlib.h>
#define Empty 0 /* 栈空 */
#define Avail 1 /* 栈可用 */ typedef struct SNode
{
int data;
struct SNode *next;
}StackNode;
typedef struct LStack
{
StackNode *top; /* 栈顶指针 */
StackNode *bottom; /* 栈底指针 */
int height; /* 链式栈高度 */
}LinkStack; LinkStack InitStack (LinkStack pStack); /* 栈顶指针、栈底指针、栈高度初始化*/
LinkStack Push (LinkStack pStack); /* 入栈 */
LinkStack Pop (LinkStack pStack); /* 出栈 */
int StackEmpty (LinkStack pStack); /* 判断栈是否为空 */
LinkStack DeletStack (LinkStack pStack);/* 清空栈 */
void DisplyStack (LinkStack pStack); /* 遍历栈----自顶至底*/ int main()
{
LinkStack p;
char ch; p.height = ; /* 栈高度初始化为零 */
p = InitStack (p); /* 栈初始化 */
printf("Do you want to push stack(Y/N)?");
scanf(" %c", &ch);
while (ch == 'Y' || ch == 'y')
{
p = Push(p); /* 入栈 */
DisplyStack(p); /* 遍历栈 */
printf("Do you want to push stack(Y/N)?");
scanf(" %c", &ch);
}
printf("Do you want to pop stack(Y/N)?");
scanf(" %c", &ch);
while (ch == 'Y' || ch == 'y')
{
p = Pop(p); /* 出栈 */
DisplyStack(p); /* 遍历栈 */
printf("Do you want to pop stack(Y/N)?");
scanf(" %c", &ch);
} return ;
}
/* Function: 初始化栈顶、栈底、栈高度*/
LinkStack InitStack (LinkStack pStack)
{
pStack.top = pStack.bottom = NULL;
pStack.height = ; return pStack;
} /* Function: 判断栈是否为空 */
int StackEmpty (LinkStack pStack)
{
if (pStack.top == NULL && pStack.bottom == NULL)
{
return Empty;
}
else
{
return Avail;
}
} /* Function: 入栈 */
LinkStack Push (LinkStack pStack)
{
int data;
StackNode *temp; if ((temp = (StackNode *)malloc(sizeof(StackNode))) == NULL)
{
printf("内存空间不足\n");
return pStack;
}
if (StackEmpty(pStack) == Empty) /* 如果栈为空 */
{
pStack.top = pStack.bottom = temp; /* 栈顶、栈底指针都指向新建节点 */
temp->next = NULL; /* 节点指针域为空 */
printf("Please input data");
scanf("%d", &data);
pStack.top->data = data;
pStack.height++; return pStack;
}
else /* 栈不为空 */
{
temp->next = pStack.top;/* 新建节点指向原来的栈顶 */
pStack.top = temp; /* 栈顶指针指向新建节点 */
printf("Please input data");
scanf("%d", &data);
pStack.top->data = data;
pStack.height++; return pStack;
}
} /* Function: 出栈 */
LinkStack Pop (LinkStack pStack)
{
StackNode *Second; if (StackEmpty(pStack) == Empty) /* 判断栈是否为空 */
{
printf("栈为空,无法出栈\n");
return pStack;
}
if (pStack.top == pStack.bottom) /* 如果出栈的元素为最后一个元素 */
{
printf("出栈元素为%d\n", pStack.top->data);
free(pStack.top);
pStack.top = pStack.bottom = NULL; /* 栈顶、栈底都指针都置为空 */
pStack.height--; return pStack;
}
printf("出栈元素为%d\n", pStack.top->data);
Second = pStack.top->next; /* 指向栈顶的前一个元素*/ free(pStack.top); /* 释放栈顶节点 */
pStack.top = Second;/* 将头指针移动到新的栈顶节点 */
pStack.height--; return pStack;
} /* Function: 遍历栈 自顶到底*/
void DisplyStack (LinkStack pStack)
{
if (StackEmpty(pStack) == Empty)
{
printf("栈为空,无法遍历\n");
return ;
}
printf("栈中元素[");
while (pStack.top != NULL)
{
printf("%d->", pStack.top->data);
pStack.top = pStack.top->next;
}
printf("]\n");
} /* Function: 清空栈 */
LinkStack DeletStack (LinkStack pStack)
{
StackNode *del; while (pStack.top != NULL)
{
del = pStack.top->next; /* 栈顶节点的前一个节点 */
free(pStack.top); /* 释放节点 */
pStack.top = del; /* 栈顶指针移动到新栈顶 */
} return pStack;
}
栈(链式栈)----C语言的更多相关文章
- 大数据全栈式开发语言 – Python
前段时间,ThoughtWorks在深圳举办一次社区活动上,有一个演讲主题叫做“Fullstack JavaScript”,是关于用JavaScript进行前端.服务器端,甚至数据库(MongoDB) ...
- 为什么说Python 是大数据全栈式开发语言
欢迎大家访问我的个人网站<刘江的博客和教程>:www.liujiangblog.com 主要分享Python 及Django教程以及相关的博客 交流QQ群:453131687 原文链接 h ...
- 数据结构——栈(C语言实现)
#include <stdio.h> #include <stdlib.h> #include<string.h> #include<malloc.h> ...
- 栈的C语言实现
在C++中,可以直接使用std::stack C语言实现如下: stack.c /** * @file stack.c * @brief 栈,顺序存储. * * * */ #include <s ...
- 【数据结构】之栈(Java语言描述)
在前面的[这篇文章]中,我简单介绍了栈这种数据结构的操作功能,并使用C语言对其进行了代码的编写. Java的JDK中默认为我们提供了栈这种数据结构的API—— Stack . Java中的Stack类 ...
- 【数据结构】之栈(C语言描述)
栈(Stack)是编程中最常用的数据结构之一. 栈的特点是“后进先出”,就像堆积木一样,堆的时候要一块一块堆到最上面,拆的时候需要从最上面一块一块往下拆.栈的原理也一样,只不过它的操作不叫堆和拆,而是 ...
- 链式栈-C语言实现
相对于顺序栈的空间有限,链式栈的操作则更加灵活 #include<stdio.h> #include<malloc.h> typedef int SElemType; //元素 ...
- 天勤考研数据结构笔记—栈的C语言实现
栈的基本概念 栈的定义:栈是一种只能在一端进行插入或删除操作的线性表.其中允许进行插入或删除的一端称为栈顶(top).栈顶是由一个称为栈顶指针的位置指示器(其实就是一个变量,对于顺序栈,就是数组索引, ...
- 栈在go语言中实现,及解决388.文件的最长绝对路径的思路
今天在LeetCode刷每日一题,遇到了388. 文件的最长绝对路径的思路,这道题让我想到了系统的目录是栈结构,果然在题解中找到了栈的解法(暴力半天没出来,跑去看题解了QWQ). 所以我就捎带复习了一 ...
- 链栈的C语言实现
/* 功能:栈的链表实现 Author:lxm Date: 20160511 */ #include <stdio.h> #include <stdlib.h> #define ...
随机推荐
- 【搜索】Dungeon Master
Description You are trapped in a 3D dungeon and need to find the quickest way out! The dungeon is co ...
- pom.xml如何引入项目jar包
<dependency> <groupId>com.jacob</groupId> <artifactId>jacob</artifactId&g ...
- 【转】python 修改os环境变量
举一个很简单的例子,如果你发现一个包或者模块,明明是有的,但是会发生这样的错误: >>> from algorithm import *Traceback (most recent ...
- 介绍用C#和VS2015开发基于Unity架构的2D、3D游戏的技术
[Unity]13.3 Realtime GI示例 摘要: 分类:Unity.C#.VS2015 创建日期:2016-04-19 一.简介 使用简单示例而不是使用实际示例的好处是能让你快速理解光照贴图 ...
- nullptr(c++11)
1.概念 用字面值常量nullptr来初始化或赋值来得到空指针 2.c++11之前使用NULL或0 1)NULL是一个宏定义(预处理变量),定义在cstdlib中,其值就是0:对于预处理变量,预处理器 ...
- web程序打包详解
重要更新:鉴于很多小伙伴们说看不到图,我这边换了几个浏览器看了下,都看得到的,估计是网速问题,请耐心等待,另外,为了更好的方便大家学习,特此提供源码以及一个word文档,word文档就是本文内容 ...
- 微信小程序之画布
canvas 标签默认宽度300px.高度225px 同一页面中的 canvas-id 不可重复,如果使用一个已经出现过的 canvas-id,该 canvas 标签对应的画布将被隐藏并不再正常工作 ...
- iOS程序的执行顺序 和 UIViewController的生命周期
iOS程序的执行顺序 1 进入程序的入口 进入main函数, 设置AppDelegate称为函数的代理 2 程序完成加载 -[AppDelegate application:didFinishLau ...
- sys/time.h 和 time.h
今天在燕麦工作第二天.看荣哥给我的程序,发现程序里面用的延时跟我以前使用的不同.导入两个头文件,然后用函数来获得时间.关于这个函数特别查来一下. time.h 是ISO C99 标准日期头文件. s ...
- (求凹包) Bicycle Race (CF 659D) 简单题
http://codeforces.com/contest/659/problem/D Maria participates in a bicycle race. The speedway t ...