【数据结构】-链栈(带头结点)

链栈-带头结点

  • 1.头文件及类型定义
  • 2.链栈类型定义
  • 3.函数声明
  • 4.基本操作
    • 4.1 初始化链栈
    • 4.2 判空
    • 4.3 入栈
    • 4.4 出栈
    • 4.5 读取栈顶元素
    • 4.6 main函数
  • 5.小结

1.头文件及类型定义

#include<stdio.h>
#include<stdlib.h>
#define ElemType int			

2.链栈类型定义

typedef struct LinkStackNode {		//链栈类型定义
	ElemType data;					//数据域
	struct LinkStackNode* next;		//指针域
}SNode,*LiStack;

3.函数声明

/*函数声明*/
bool InitLinkStack(LiStack& S);			//1.初始化链栈
bool LiStackEmpty(LiStack S);			//2.判空
bool Push(LiStack& S, ElemType e);		//3.入栈
bool Pop(LiStack& S, ElemType& e);		//4.出栈
bool GetTop(LiStack S, ElemType& e);	//5.读取栈顶元素

4.基本操作

4.1 初始化链栈

//1.初始化栈(带头结点)
bool InitLinkStack(LiStack& S) {
	S = (SNode*)malloc(sizeof(SNode));		//分配头结点
	if (S == NULL)
		return false;		//内存不足,分配失败
	S->next = NULL;		//头结点之后暂时没有结点
	return true;
}

4.2 判空

//2.判空
bool LiStackEmpty(LiStack S) {
	return (S->next == NULL);
}

4.3 入栈

//3.入栈操作
bool Push(LiStack& S, ElemType e) {
	SNode* p = (SNode*)malloc(sizeof(SNode));
	if (p == NULL)		//内存分配失败
		return false;
	p->data = e;
	p->next = S->next;
	S->next = p;
	return true;
}

4.4 出栈

//4.出栈操作
bool Pop(LiStack& S, ElemType& e) {
	if (S->next == NULL)
		return false;		//栈空,报错
	SNode* q = S->next;		//找到当前链栈的栈顶结点
	e = q->data;			//返回栈顶结点的值
	S->next = q->next;
	free(q);
	return true;
}

4.5 读取栈顶元素

//5.读取栈顶元素操作
bool GetTop(LiStack S, ElemType& e) {
	if (S->next == NULL)
		return false;		//栈空,报错
	e = S->next->data;
	return true;
}

4.6 main函数

int main() {
	LiStack S;		//声明一个链栈

	/*1、初始化栈*/
	InitLinkStack(S);

	/*2、判空*/
	if (LiStackEmpty(S))
		printf("当前链栈为空!\n");
	else
		printf("当前链栈非空!\n");

	/*3、入栈操作*/
	ElemType e1;
	printf("请输入入栈元素的值:");
	scanf("%d", &e1);
	if (Push(S, e1))
		printf("新元素入栈成功!\n");
	else
		printf("栈已满,新元素入栈失败!\n");


	/*4、读取栈顶元素*/
	ElemType e2 = -1;
	if (GetTop(S, e2))
		printf("读取栈顶元素成功,当前栈顶元素值为:%d\n", e2);
	else
		printf("栈已空,读取栈顶元素失败!\n");

	/*5、出栈操作*/
	ElemType e3 = -1;
	if (Pop(S, e3))
		printf("栈顶元素出栈成功,出栈元素值为:%d\n", e3);
	else
		printf("栈已空,栈顶元素出栈失败!\n");

	/*6、读取栈顶元素*/
	ElemType e4 = -1;
	if (GetTop(S, e4))
		printf("读取栈顶元素成功,当前栈顶元素值为:%d\n", e4);
	else
		printf("栈已空,读取栈顶元素失败!\n");

	return 0;
}

5.小结

  1. 关于带头结点和不带头结点的链栈
    总的来说,跟带头结点和不带头结点的单链表的区别是一样的。只不过在实现上来说,上篇不带头结点的链表的结构体仅声明了LiStack,表示链栈,本文中则分别声明了SNode和LiStack,表示链栈结点和链栈,其实二者是等价的(SNode*等价于LiStcak)只不过为了强调是链栈还是链栈结点。
  2. 对比单链表和链栈在头结点上的差异
    首先给出结论:一般情况下链栈不带头结点而单链表要带头结点。
    主要是因为链表在插入删除时有头部和其他部位的操作差别,引入头结点来统一操作,使对链表第一个位置上的操作和其他位置上的操作相同,不用特殊处理。而链栈只在头部插入删除,所以不必要用头结点。
    但无论是带头结点还是不带头结点的链表和链栈都要会写(好像是句废话hhhhhh)

你可能感兴趣的:(数据结构)