数据结构之栈基本操作

目录

一、栈

二、实现栈

1. 顺序栈

2. 链栈

3. 共享栈


一、栈

        栈(stack)是只允许在一端进行插入或删除操作的线性表,它是一种操作受限的线性表。

        栈顶: 线性表允许进行插入删除的那一端。

        栈底: 不允许进行插入和删除的那一端。

        空栈: 不含有任何元素的空表。

栈的基本操作:

  •         InitStack(Stack &s): 初始化栈
  •         StackEmpty(Stack s): 判断一个栈是否为空
  •         Push(Stack &s, ElemType x): 入栈
  •         Pop(Stack &s, ElemType &x): 出栈
  •         GetTop(Stack s, ElemType &x): 获取栈顶元素
  •         DestroyStack(Stack &s): 销毁栈
  •         PrintStack(Stack s): 遍历栈

基于以上七种操作,我将从栈的不同存储结构出发,实现这些基本操作。

二、实现栈

1. 顺序栈

#include <stdio.h>

#define MAX_SIZE 10

typedef int ElemType;

// 顺序栈
typedef struct {
	ElemType data[MAX_SIZE];
	int top; // 指向可插入的位置
} SqStack;

// 初始化栈
void InitStack(SqStack &s) {
	s.top = 0;
}

// 栈空判断
bool StackEmpty(SqStack &s) {
	return s.top == 0 ? true : false;
}

// 入栈
bool push(SqStack &s, ElemType x) {
	if (s.top == MAX_SIZE) {
		printf("栈已满,不能继续添加元素啦!\n");
		return false;
	}
	s.data[s.top++] = x;
	return true;
}

// 出栈
bool pop(SqStack &s) {
	if (StackEmpty(s)) {
		printf("很抱歉,此时栈为空。\n");
		return false;
	}
	s.data[s.top--] = 0;
	return true;
}

// 取栈顶元素
ElemType GetTop(SqStack s) {
	return s.data[s.top - 1];
}

// 销毁栈,逻辑上销毁
void DestroyStack(SqStack &s) {
	s.top = 0;
}

// 打印顺序栈
void PrintStack(SqStack s) {
	if (StackEmpty(s)) {
		return;
	}
	int i = s.top - 1;
	while (i >= 0) {
		printf("%d ", s.data[i]);
		i--;
	}
	printf("\n");
}

int main() {
	SqStack s;
	InitStack(s);
	push(s, 1);
	push(s, 2);
	push(s, 3);
	pop(s);
	push(s, 4);
	ElemType x = GetTop(s);
	printf("栈顶元素为:%d\n", x);
	PrintStack(s);
	pop(s);
	pop(s);
	PrintStack(s);
	DestroyStack(s);
	PrintStack(s);
}

顺序栈使用一段连续空间来存储栈,通过设置top指针指向栈顶元素或可插入元素的位置,来表示栈结构。 

2. 链栈

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

typedef int ElemType;

// 链栈
typedef struct LinkNode {
	ElemType data;
	LinkNode *next;
} LiStack;

// 初始化栈
void InitStack(LiStack &s) {
	s.next = NULL;
}

// 判断栈空
bool StackEmpty(LiStack s) {
	return s.next == NULL ? true : false;
}

// 入栈
void Push(LiStack &s, ElemType e) {
	LinkNode *p = (LinkNode *) malloc(sizeof(LinkNode));
	p->data = e;
	p->next = s.next;
	s.next = p;
	printf("进栈元素是%d\n", e);
}

// 取栈顶元素
ElemType GetTop(LiStack s) {
	return s.next->data;
}

// 出栈
ElemType Pop(LiStack &s) {
	if (StackEmpty(s)) {
		return -1;
	}
	LinkNode *p = s.next;
	ElemType data = GetTop(s);
	s.next = p->next;
	free(p);
	printf("出栈元素是%d\n", data);
	return data;
}

// 打印链栈中的全部元素
void PrintStack(LiStack s) {
	if (StackEmpty(s)) {
		printf("当前栈为空!\n");
		return;
	}
	LinkNode *p = s.next;
	while (p != NULL) {
		printf("%d ", p->data);
		p = p->next;
	}
	printf("\n");
}

void DestroyStack(LiStack &s) {
	LinkNode *q, *p = s.next;
	while (p != NULL) {
		q = p;
		p = p->next;
		free(q);
	}
	s.next = NULL;  // 将链栈的头指针置为 NULL
	printf("成功销毁链栈!\n");
}

int main() {
	LiStack s;
	InitStack(s);
	Push(s, 10);
	Push(s, 5);
	Push(s, 1);
	Push(s, 20);
	PrintStack(s);
	ElemType e = GetTop(s);
	printf("栈顶元素为%d\n", e);
	Pop(s);
	Pop(s);
	PrintStack(s);
	DestroyStack(s);
	PrintStack(s);
}

链栈通过一组任意的存储单元来栈中的元素,但链栈是操作受限的线性表,它只允许从表头进栈,通过头插法可以实现。

3. 共享栈

#include <stdio.h>

#define MAX_SIZE 10

typedef int ElemType;
// 共享栈
typedef struct {
	ElemType data[MAX_SIZE];
	int top; // 指向栈顶 0号栈
	int base; // 指向栈底 1号栈
} ShareStack;

// 初始化共享栈
void InitStack(ShareStack &s) {
	s.base = -1;
	s.top = MAX_SIZE;
}

// 判断共享栈为空
bool StackEmpty(ShareStack s) {
	return (s.base == -1 && s.top == MAX_SIZE) ? true : false;
}

// 判断共享栈是否已满
bool StackFull(ShareStack s) {
	return (s.top - s.base == 1) ? true : false;
}

// 入栈
bool Push(int type, ShareStack &s, ElemType e) {
	if (StackFull(s)) {
		printf("当前栈已满!\n");
		return false;
	}
	if (type == 1) {
		// 表示1号栈,栈底
		s.data[++s.base] = e;
	}
	if (type == 0) {
		// 表示0号栈,栈顶
		s.data[--s.top] = e;
	}
	return true;
}

ElemType GetTop(int type, ShareStack s) {
	ElemType data;
	if (type == 1) {
		data = s.data[s.base];
	}
	if (type == 0) {
		data = s.data[s.top];
	}
	return data;
}

// 出栈
ElemType Pop(int type, ShareStack &s) {
	if (StackEmpty(s)) {
		printf("当前栈为空,没有可以出栈的元素!\n");
		return NULL;
	}
	ElemType e = GetTop(type, s);
	if (type == 1) {
		--s.base;
	}
	if (type == 0) {
		++s.top;
	}
	printf("出栈元素是%d\n", e);
	return e;
}

// 打印栈元素
void PrintStack(int type, ShareStack s) {
	if (type == 1) {
		printf("1号栈的元素有:");
		int index = s.base;
		while (index >= 0) {
			printf("%d ", s.data[index--]);
		}
		printf("\n");
	}
	if (type == 0) {
		printf("0号栈的元素有:");
		int index = s.top;
		while (index < MAX_SIZE) {
			printf("%d ", s.data[index++]);
		}
		printf("\n");
	}
}

// 销毁共享栈
void DestroyShareStack(ShareStack &s) {
	s.top = MAX_SIZE;
	s.base = -1;
}

int main() {
	ShareStack s;
	InitStack(s);
	Push(1, s, 5);
	Push(1, s, 5);
	Push(1, s, 1);
	Push(1, s, 3);
	Push(1, s, 10);
	Push(0, s, -10);
	Push(0, s, -5);
	Push(0, s, 0);
	Push(0, s, -1);
	Push(1, s, 100);
	Push(0, s, 2);
	PrintStack(1, s);
	PrintStack(0, s);
	Pop(0, s);
	Pop(1, s);
	Pop(0, s);
	PrintStack(1, s);
	PrintStack(0, s);
	DestroyShareStack(s);
}

共享栈是指同一片连续空间,分别从相对方向存放各个栈的元素,它节省了所需的空间,不同于顺序栈的是,在判断栈满时,是通过判断两个栈顶指针对应的索引关系。 


        栈的数据结构本质上和线性表是相同的,在陈述内容时,更多的是不同存储结构下的栈的基本操作的实现。上述内容如果有错误的地方,希望大佬们可以指正。我一直在学习的路上,您的帮助使我收获更大!觉得对您有帮助的话,还请点赞支持!我也会不断更新文章! 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

弘弘弘弘~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值