数据结构篇栈第二弹---静态栈和链栈的实现

前言

参考书籍 :《大话数据结构》
编程语言:C语言。
涉及的头文件,后面代码省略了,请自行补上。

#include<stdio.h>
#include<assert.h>

动态栈实现—更完整的介绍栈

栈的定义(回顾)

栈的定义:栈是一种特殊的线性表。栈限定仅在表尾进行插入和删除操作。
其中允许在一端进行数据的插入与删除的操作,被称为栈顶,而另一端则被称为栈底。
专业名词:
出栈:删除尾端的元素。
入栈/压栈/进栈:往尾端插入元素。
空栈:没有存储任何元素。
后进先出

顺序结构(定长数组)实现栈—静态栈

由于大话数据结构这本书采取的是定长数组实现栈,所以先说明这种。
实现栈的函数。
//栈的初始化

//压栈操作
//出栈操作
//栈的销毁

大体写那些函数就行了,后面遇到要额外写的函数后面再补上就是。

栈的长度:栈的有效数据的元素个数。
设计思路:定长数组的下标为0处为栈底,数组最大下标实际有效长度减一作为栈顶,那么top指向的就是栈顶的有效元素,top+1是下一位插入元素的位置

#define MAX_COUNT 100
typedef int StackDataType;//StackDataType根据实际情况而定,这里假设为int。
typedef struct stack {
	int top;//栈顶指针
	StackDataType data[MAX_COUNT];//定长数组
}ST;

栈的初始化

void STInit(ST* ps) {
	assert(ps);
	ps->top = -1;
	int i = 0;
	for (i = 0; i < MAX_COUNT; i++) {
		ps->data[i] = 0;
	}
}

栈的销毁

void STDestory(ST* ps) {
	STInit(ps);//局部变量出作用域自动销毁,不用特地销毁。
}

压栈

void STPush(ST* ps,StackDataType x) {
	assert(ps);
	//判断栈满了没
	assert(ps->top != MAX_COUNT);
	ps->data[++ps->top] = x;
	 
}

出栈

void STPop(ST* ps) {
	assert(ps);
	//判断是否为空栈
	assert(ps->top != -1);
	--ps->top;
}

栈打印

void STPrint(ST* ps) {
	assert(ps);
	int i = 0;
	for (i = 0; i <50; i++)
		printf("-");
	printf("\n|");
	for (i = 0; i <= ps->top; i++)
	{
		printf("%d->", ps->data[i]);
	}
	printf("null\n");
	for (i = 0; i < 50; i++)
		printf("-");
	printf("\n");
}

简单评价一下静态栈

压栈出栈时间复杂度O(1),快。连续的物理空间存储数据。
缺点浪费空间,不灵活。实际中并不适用。

链式结构实现栈—链栈

链式结构肯定用链表呗,用哪种链表呢?
显然单链表,单向不循环链表。带哨兵位方便,带头结点。
单链表的头部很适合作为栈顶。为什么不选择尾部?因为单链表的毒点就是进行尾插尾删要遍历整个链表找尾。选头部最适合。

压栈:即(带哨兵位)单链表的头插。
出栈:即(带哨兵位)单链表头删。

链栈的定义

typedef int StackDataType;
typedef struct stack {
	StackDataType data;
	struct stack* next;
}ST;
ST* top = NULL;//栈顶指针
ST* base = NULL;//栈底指针,也就是头指针指向哨兵位。
#include<assert.h>
#include<stdio.h>
#include<stdlib.h>

typedef int StackDataType;
typedef struct stack {
	StackDataType data;
	struct stack* next;
}ST;
ST* STBuyNode(StackDataType x);
ST* STInit(void) {
	ST* tmp = (ST*)malloc(sizeof(ST));
	if (tmp == NULL) {
		perror("malloc fail");
		exit(-1);
	}
	tmp->data = -1;
	tmp->next = NULL;
	return tmp;
}
void STPush(ST** pphead,StackDataType x) {
	assert(pphead);
	assert(*pphead);
	ST* newnode = STBuyNode(x);
	newnode->next = *pphead;
	*pphead = newnode;
}

void STPrint(ST* phead) {
	if (phead==NULL) {
		printf("NULL");
		return;
	}
	ST* pcur = phead;
	while (pcur->next)
	{
		printf("%d->", pcur->data);
		pcur = pcur->next;
	}
	printf("哨兵位->NULL\n");
}
void STPop(ST** pphead) {
	assert(pphead);
	assert(*pphead);
	assert((*pphead)->next);//判断此处是不是哨兵位,如果是则不能在头删了。
	//改变栈顶指针的指向。
	ST* tmp = *pphead;
	*pphead = (*pphead)->next;
	free(tmp);
}
ST* STBuyNode(StackDataType x) {
	ST* newnode = (ST*)malloc(sizeof(ST));
	if (newnode == NULL) {
		perror("malloc fail!");
		exit(-1);
	}
	newnode->data = x;
	newnode->next = NULL;
	return newnode;
}

void STDestory(ST** top,ST** base) {
	assert(top && base);
	assert(*top && *base);
	ST* pcur = *top;
	ST* next = *top;
	while (pcur) {
		next = pcur->next;
		free(pcur);
		pcur = next;
	}
	*top = NULL;
	*base = NULL;
}
int main() {
	ST* top = NULL;//栈顶指针
	ST* base = NULL;//栈底指针,也就是头指针指向哨兵位。
	top = base = STInit();
	STPush(&top, 1);
	STPush(&top, 1);
	STPush(&top, 1);
	STPrint(top);
	STPop(&top);
	STPrint(top);
	STDestory(&top, &base);
	STPrint(top);

	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值