栈(链式栈)----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 ...
随机推荐
- 微信小程序开发工具常用快捷键
格式调整 Ctrl+S:保存文件 Ctrl+[, Ctrl+]:代码行缩进 Ctrl+Shift+[, Ctrl+Shift+]:折叠打开代码块 Ctrl+C Ctrl+V:复制粘贴,如果没有选中任何 ...
- 20155312 实验一《Java开发环境的熟悉》实验报告
(一)命令行下Java程序开发 截图如下: 打印学号: 遇到的问题及 编译时如果还使用javac -d bin 文件名,就会出错 解决:package包是将编译文件放入指定包中 注意:代码中有pack ...
- 树状数组(hdu-4325,hdu-1166,pat-1057)
1.hdu-4325 题意:插花,要么给出插花的范围,要么查询某个点的花的个数. 思路:通过更新,每次更新区间S到T的数值,表插入花(这一点一开始没想到), 要么查询某个点的花的数目. (与以往单纯的 ...
- sprintf()与sscanf()
1.sprintf() sprintf()用于向字符串中写入格式化的数据,eg: int dSrc1 = 1; int dSrc2 = 2; char str[] = "hello" ...
- CSS Sprites (CSS 精灵) 技术
CSS Sprites在国内很多人叫css精灵,是一种网页图片应用处理方式.它允许你将一个页面涉及到的所有零星图片都包含到一张大图中去,这样一来,当访问该页面时,载入的图片就不会像以前那样一幅一幅地慢 ...
- string流
istringstream和ostringstream 从istringstream类中读取数据赋值给某个string,写入某个string到ostringstream类,头文件<sstream ...
- jquery删除onclick属性和设置onclick属性--获取验证码
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- JQuery设置和去除disabled属性 与 display显示隐藏
//两种方法设置disabled属性 $('#areaSelect').attr("disabled",true); $('#areaSelect').attr("dis ...
- maven之web工程的搭建
参考之前jave application的工程创建的步骤,我们只需要修改最后一步 这样就创建了个web maven工程 与java application应用程序的区别,还有别的区别这里不做多的阐述. ...
- linux下的各个目录(待填)
/系统目录 / 下的目录: 1./bin(binary,二进制文件):打开里面会发现全是绿色的文件,也就是可执行文件,而且名字都是系统命令的名字,其实每个系统命令都是一个小的可执行的文件,这些命令都存 ...