链式栈:就是一种操作受限的单向链表,对单向链表还不了解的可先看一下之前的一篇关于单向链表的随笔,链表(单向链表的建立、删除、插入、打印),理解了单向链表后再来看链式栈就比较轻松了

链式栈的操作一般含有:出栈、入栈、栈的初始化、判断栈是否为空、清空栈,下面先上声明部分代码

 #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语言的更多相关文章

  1. 大数据全栈式开发语言 – Python

    前段时间,ThoughtWorks在深圳举办一次社区活动上,有一个演讲主题叫做“Fullstack JavaScript”,是关于用JavaScript进行前端.服务器端,甚至数据库(MongoDB) ...

  2. 为什么说Python 是大数据全栈式开发语言

    欢迎大家访问我的个人网站<刘江的博客和教程>:www.liujiangblog.com 主要分享Python 及Django教程以及相关的博客 交流QQ群:453131687 原文链接 h ...

  3. 数据结构——栈(C语言实现)

    #include <stdio.h> #include <stdlib.h> #include<string.h> #include<malloc.h> ...

  4. 栈的C语言实现

    在C++中,可以直接使用std::stack C语言实现如下: stack.c /** * @file stack.c * @brief 栈,顺序存储. * * * */ #include <s ...

  5. 【数据结构】之栈(Java语言描述)

    在前面的[这篇文章]中,我简单介绍了栈这种数据结构的操作功能,并使用C语言对其进行了代码的编写. Java的JDK中默认为我们提供了栈这种数据结构的API—— Stack . Java中的Stack类 ...

  6. 【数据结构】之栈(C语言描述)

    栈(Stack)是编程中最常用的数据结构之一. 栈的特点是“后进先出”,就像堆积木一样,堆的时候要一块一块堆到最上面,拆的时候需要从最上面一块一块往下拆.栈的原理也一样,只不过它的操作不叫堆和拆,而是 ...

  7. 链式栈-C语言实现

    相对于顺序栈的空间有限,链式栈的操作则更加灵活 #include<stdio.h> #include<malloc.h> typedef int SElemType; //元素 ...

  8. 天勤考研数据结构笔记—栈的C语言实现

    栈的基本概念 栈的定义:栈是一种只能在一端进行插入或删除操作的线性表.其中允许进行插入或删除的一端称为栈顶(top).栈顶是由一个称为栈顶指针的位置指示器(其实就是一个变量,对于顺序栈,就是数组索引, ...

  9. 栈在go语言中实现,及解决388.文件的最长绝对路径的思路

    今天在LeetCode刷每日一题,遇到了388. 文件的最长绝对路径的思路,这道题让我想到了系统的目录是栈结构,果然在题解中找到了栈的解法(暴力半天没出来,跑去看题解了QWQ). 所以我就捎带复习了一 ...

  10. 链栈的C语言实现

    /* 功能:栈的链表实现 Author:lxm Date: 20160511 */ #include <stdio.h> #include <stdlib.h> #define ...

随机推荐

  1. mysql 5.7 linux环境下解压安装

    在CentOS linux环境安装mysql 一般rpm(或者yum),预编译和源码安装. 如果采用rpm或者yum安装,mysql的数据文件一般存放在/var/lib/mysql目录下,也就是会把d ...

  2. android OkHttpUtils 使用JSON数据作为请求参数

    如果就直接将JSON作为请求字符串,服务端会出现中文乱码.所以只需要将请求的整个JSON参数字符串编码一次,然后服务端解码一次.我这里服务端使用的servlet,下面会两段代码贴出. android: ...

  3. redis 的一主二从三哨兵模式

    概述 在部署redis 的时候,如果redis宕机,缓存将不可用,redis提供了哨兵模式保证redis实现高可用. 即一台主机两台从机,三台哨兵主机,如果主实例宕机,哨兵将将一台从机升级为主机.实现 ...

  4. 第15章 上下文管理器和else块

    #<流流畅的Python>第15章 上下文管理器和else块 #15.1 先做这个,再做那个:if语句之外的else块 #else子句不仅能在if语句中使用,还能在for.while和tr ...

  5. ssh 认证

    ssh 秘钥认证流程 ssh配置认证 基于口令(密码)的安全验证 [root@m01 ~]# ssh 10.0.0.41 hostname root@10.0.0.41's password: bac ...

  6. servlet 解决乱码问题

    对于servlet大家应该都很熟悉了,今天再复习一下,如果有哪里写的不好或不对的地点希望广大的网友批评指正.今天只讨论get和post两w种方式,他们之间有很多的不同点,所以解决编码的方式也会不一样, ...

  7. asp.net微信支付发起页面jsapi.aspx

    jsapi.aspx 后台核心代码 //创建支付应答对象 RequestHandler packageReqHandler = new RequestHandler(Context); //初始化 p ...

  8. Using Spring.net in console application

    Download Spring.net in http://www.springframework.net/ Install Spring.NET.exe Create a console appli ...

  9. js获取标签下标

    <body> <div class="titTab"> <span>低</span> <span>中</span& ...

  10. activity之间如何传递list

    可以把list的内容拼成json串再去解析