C语言实现链栈的步骤

链栈图解

链栈的常规操作

/********************* 链栈的常规操作 ****************************/

LinkStack 	 InitLinkStack();			// 初始化链栈
int   	 	 StackEmpty();				// 判断链栈空
int   	 	 StackLength();				// 求链栈长(链栈元素个数)
int    		 Push();					// 入栈 压栈
ElemType 	 Pop();						// 出栈 弹栈
void 	 	 DestroyStack();			// 销毁链栈

/***************************************************************/

定义链栈结构体

#include "stdio.h"
#include "malloc.h"

#define TRUE  1
#define FALSE 0

typedef int ElemType;		// 链栈存储元素的数据类型

/*
 *	定义链栈结构体
*/
typedef struct Node{
	ElemType data;			// 栈结点数据域
	struct Node *next;		// 栈结点指针域
}*LinkStack, Node;

初始化链栈

// 初始化链栈(带头结点的链栈)
LinkStack InitLinkStack(){
	LinkStack s = (LinkStack)malloc(sizeof(struct Node));
	s -> next = NULL;
	return s;
}

链栈判空

/*
 *	判断链栈是否空
 *  s 链栈
*/
int StackEmpty(LinkStack s){
	if(s == NULL){
		return FALSE;
	}
	return s -> next == NULL;
}

因为是链式存储结构,无需链栈判满。

计算链栈的长度

/*
 *	求链栈长度(栈中元素个数)
 *  s 链栈
*/
int StackLength(LinkStack s){
	LinkStack p;
	int len = 0;
	if(StackEmpty(s)){
		return FALSE;
	}
	p = s -> next;	// 带头结点的链栈要先移动一下
	while(p != NULL){
		len ++;
		p = p -> next;
	}
	return len;
}

链栈入栈(Push)

/*
 *	入栈 压栈
 *  s 链栈
 *  data 入栈数据
*/
int Push(LinkStack s, ElemType data){
	// 分配入栈结点
	Node *new_node = (Node *)malloc(sizeof(struct Node));
	if (new_node == NULL) return FALSE;		// 结点分配失败

	// 跟单链表一样使用头插法
	new_node -> data = data;
	new_node -> next = s -> next;
	s -> next = new_node;
	return TRUE;
}

链栈出栈(Pop)

/*
 *	出栈 弹栈
 *	s 链栈
*/
ElemType Pop(LinkStack s){
	LinkStack top;
	ElemType data;
	// 判栈空
	if(StackEmpty(s)){
		return FALSE;
	}
	top = s -> next;	// 访问栈顶结点
	data = top -> data;	// 取出栈顶元素
	s -> next = top -> next;
	free(top);			// 释放栈顶空间
	return data;
}

链栈各操作测试

// 程序主入口
int main(int argc, char const *argv[])
{
	LinkStack s = InitLinkStack();
	printf("StackEmpty():%d\n", StackEmpty(s));
	printf("StackLength():%d\n\n", StackLength(s));

	// 入栈元素
	ElemType datas[] = {1, 3, 5, 7, 9};

	// 动态计算入栈元素个数
	int len = sizeof(datas) / sizeof(datas[0]);	

	// for循环依次入栈
	printf("Push():");
	for(int i = 0; i < len; i++){
		printf("%d\t", datas[i]);
		Push(s, datas[i]);
	}
	printf("\nStackEmpty():%d\n", StackEmpty(s));
	printf("StackLength():%d\n\n", StackLength(s));

	// 出栈 弹栈
	printf("Pop(): ");
	while(!StackEmpty(s)){
		printf("%d\t", Pop(s));
	}
	printf("\nStackEmpty():%d\n", StackEmpty(s));
	printf("StackLength():%d\n\n", StackLength(s));
	return 0;
}

结果如下:

StackEmpty():1
StackLength():0

Push():1        3       5       7       9
StackEmpty():0
StackLength():5

Pop(): 9        7       5       3       1
StackEmpty():1
StackLength():0

源代码

源代码已上传到 GitHub Data-Structure-of-C,欢迎大家来访。

以上就是C语言实现链栈的步骤的详细内容,更多关于C语言实现链栈的资料请关注我们其它相关文章!

(0)

相关推荐

  • C语言实现出栈序列

    本文实例为大家分享了C语言实现出栈序列的具体代码,供大家参考,具体内容如下 题目描述: 现在有一个1-n的排列,入栈序列已知,请给出字典序最大的出栈序列. 输入格式 第一行一个整数n.(1<=n<=100) 第二行n个整数,数据确保为1-n的排列. 输出格式 输出n个整数,既字典序最大的出栈序列. 输入样例 5 1 2 4 5 3 输出样例 5 4 3 2 1 解题思路: 1.获取当前数组的最大值,并且需要知道它的下标.所以定义了两个方法,getMax来获取数组的最大值maxNum,getMa

  • C/C++多参数函数参数的计算顺序与压栈顺序的示例代码

    一.前言 今天在看Thinking in C++这本书时,书中的一个例子引起了我的注意,具体是使用了下面这句 单看这条语句的语义会发现仅仅是使用一个简单的string的substr函数将所得子串push_back到strings.但是在阅读时我却对于substr的参数传递产生了疑惑,到底是先执行了++current,还是先执行了last-current? 经过查阅资料,发现了两个相关知识点----参数的计算顺序与压栈顺序. 二.参数压栈顺序 C/C++中规定了函数参数的压栈顺序是从右至左,对于含

  • TypeScript之调用栈的实现

    本文介绍了TypeScript之调用栈,分享给大家,具体如下: class CallStackTool{ private static index:number = 0; public static printCallStack (count:number , simple: boolean = true):void { let caller:Function = arguments.callee.caller; let i:number = 0; count = count || 10; Ca

  • 浅谈鸿蒙 JavaScript GUI 技术栈

    作者:doodlewind 链接:https://juejin.im/post/6872154561574862855 众所周知,刚刚开源的「鸿蒙 2.0」以 JavaScript 作为 IoT 应用开发的框架语言.这标志着继 SpaceX 上天之后,JavaScript 再一次蹭到了新闻联播级的热点.这么好的机会,只拿来阴阳怪气实在太可惜了.作为科普,这篇文章不会拿着放大镜找出代码中的槽点来吹毛求疵,而是希望通俗地讲清楚它所支持的 GUI 到底是怎么一回事.只要对计算机基础有个大概的了解,应该

  • c++如何控制对象的创建方式(禁止创建栈对象or堆对象)和创建的数量

    我们知道,C++将内存划分为三个逻辑区域:堆.栈和静态存储区.既然如此,我称位于它们之中的对象分别为堆对象,栈对象以及静态对象.通常情况下,对象创建在堆上还是在栈上,创建多少个,这都是没有限制的.但是有时会遇到一些特殊需求. 1.禁止创建栈对象 禁止创建栈对象,意味着只能在堆上创建对象.创建栈对象时会移动栈顶指针以"挪出"适当大小的空间,然后在这个空间上直接调用类的构造函数以形成一个栈对象.而当栈对象生命周期结束,如栈对象所在函数返回时,会调用其析构函数释放这个对象,然后再调整栈顶指针

  • C语言实现出栈序列合法性判定

    本文实例为大家分享了C语言实现出栈序列合法性判定的具体代码,供大家参考,具体内容如下 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序. 假设压入栈的所有数字均不相等.例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列.(注意:这两个序列的长度是相等的) 输入格式 第一行一个整数n,表示输入序列的长度.(1<=n<=10000) 第二行n个整数,表示栈的压入顺

  • C++利用栈实现中缀表达式转后缀表达式

    本文实例为大家分享了C++实现中缀表达式转后缀表达式的具体代码,供大家参考,具体内容如下 题目:现有中缀表达式如:1+(2-3)*4+10/5 请用栈的特性编写一个程序,使得程序输出后缀表达式 分析如下: STEP1: 1+(2-3)*4+10/5 首先遇到第一个输入是数字1,数字在后缀表达式中都是直接输出,接着是符号"+",入栈: STEP2: 1+(2-3)*4+10/5 第三个字符是"(",依然是符号,入栈,接着是数字2,输出,然后是符号"-&quo

  • C语言利用栈实现对后缀表达式的求解

    本文实例为大家分享了C语言实现对后缀表达式(逆波兰表达式)的求解代码,供大家参考,具体内容如下 逆波兰表达式: 逆波兰表达式又叫后缀表达式.它是由相应的语法树的后序遍历的结果得到的. 例:5 - 8*(6 + 7) + 9 / 4: 其中缀表达式为:5 - 8 * 6 + 7 + 9 / 4 其语法树如下: 因此根据语法树可以得出他后序遍历(后缀表达式)为: 5 8 6 7 + * - 9 4 / + 这样就实现了中缀表达式到后缀表达式的转换. 同样的也可以得出他的前序遍历(前缀表达式也称波兰表

  • 使用Python将Exception异常错误堆栈信息写入日志文件

    假设需要把发生异常错误的信息写入到log.txt日志文件中去: import traceback import logging logging.basicConfig(filename='log.txt', level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s') try: raise Exception('发生异常错误信息') except: #方案一,自己定义一个文件,自己把错误堆栈信息写入文件. #er

  • C++利用链栈实现表达式求值

    本文实例为大家分享了C++利用链栈实现表达式求值的具体代码,供大家参考,具体内容如下 #include<iostream.h> typedef int Status; typedef char Cstack; #define OK 1 #define ERROR 0 typedef struct StackNode { Cstack data; struct StackNode *next; }StackNode,*LinkStack; Status InitStack(LinkStack &

随机推荐