4、数据结构与算法解析(C语言版)--栈

news/2024/12/26 4:35:54 标签: c语言, 栈操作

栈的数据存储遵循“后进先出的规则”,这在计算机里面是非常有用的,比如word等编辑软件的"撤销"功能,就是使用栈进行实现的。

1、创建项目

 main.h

#ifndef _MAIN_H
#define _MAIN_H

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

#define TRUE  1
#define FALSE 0
#define OK    1
#define ERROR 0
#define INFEASIBLE -1   // 无意义 
#define OVERFLOW -2

typedef int Status;
typedef int ElemType;
typedef int SElemType;


#endif 

main.c

#include "Stack.h"

/* run this program using the console pauser or add your own getch, system("pause") or input loop */

int main(int argc, char *argv[]) {
	Stack_test();	
	
	return 0;
}

Stack.h

#ifndef _STACK_H
#define _STACK_H

#include "main.h"

void Stack_test(void);

#endif

Stack.c

#include "Stack.h"

void Stack_test(void)
{
	
}

2、创建栈结构

#ifndef _STACK_H
#define _STACK_H

#include "main.h"

#define STACK_INT_SIZE 10  // 栈初始容量为10 
#define STACK_INCREMENT 2  // 空间不够每次增加两个 

// 栈结构类型
typedef struct 
{
	SElemType *base;   // 栈底指针,栈构造和销毁后为NULL
	SElemType *top;   // 栈顶指针
	int stacksize;    // 当前栈的容量,分配的空间数		
}SqStack;

void Stack_test(void);

#endif

3、初始化栈

// 初始化栈 
// - 在函数内部修改外部栈空间的base、top、stacksize因此需要传入外部栈空间地址
void InitStack(SqStack *s) 
{
	s->base = (SElemType *)malloc(STACK_INT_SIZE *sizeof(SElemType));
	if(!s->base)
	{
		printf("申请栈空间失败\r\n");
		exit(OVERFLOW);
	}
	
	s->top = s->base;
	s->stacksize = 0;
} 

测试代码:

void Stack_test(void)
{
	SqStack st;
	InitStack(&st);
}

4、向栈中添加元素

// 向栈中添加元素
// - 在函数内部修改外部栈空间的base、top、stacksize因此需要传入外部栈空间地址
void Push(SqStack *s,SElemType e) 
{
	if(s->top - s->base == s->stacksize )
	{
		// 栈满
		SElemType *temp;
		temp =  (SElemType *)realloc(s->base,(s->stacksize + STACK_INCREMENT)*sizeof(SElemType));
		if(!temp)
		{
			printf("申请栈空间失败\r\n");
			exit(OVERFLOW);
		}
		
		s->base = temp; // 申请成功,修改s->base指向
		s->top = s->base + s->stacksize;  // 更改新的top指针指向
		s->stacksize +=  STACK_INCREMENT;		
	}
	
	// 将元素推入栈中 
	*(s->top) = e;
	// 栈顶指针移动 
	(s->top)++; 
}

5、访问栈数据

// 访问栈数据
void StackTraverse(SqStack s)
{
	SElemType *p = s.base;
	
	while(p < s.top)
	{
		printf("%d ",*p);
		p++;
	}
	printf("\n");
} 

测试代码:

void Stack_test(void)
{
	SqStack st;
	InitStack(&st);
	
	int i = 0;
	for(i=1;i<8;i++)
	{
		Push(&st,i);
	}
	
	StackTraverse(st);
}

 6、获取栈顶元素不移除

Status GetTop(SqStack s,SElemType *e)
{
	if(s.top > s.base)
	{
		// 栈不为空
		*e = *(s.top-1); 
		return OK;
	}
	
	return ERROR;
}

测试代码: 

void Stack_test(void)
{
	SqStack st;
	InitStack(&st);
	
	int i = 0;
	for(i=1;i<8;i++)
	{
		Push(&st,i);
	}
	
	printf("栈中元素有:"); 
	StackTraverse(st);
	
	SElemType res;
	GetTop(st,&res);
	printf("栈顶元素:%d\n",res);	
	
}

7、移除栈顶元素

// 移除栈顶元素
// 接收栈顶数据到外部空间中
Status Pop(SqStack *sp,SElemType *e) 
{
	if(sp->top == sp->base) 
	{
		return ERROR;
	}
	
	--(sp->top);
	*e = *(sp->top);
	return OK;
}

测试代码:

void Stack_test(void)
{
	SqStack st;
	InitStack(&st);
	
	int i = 0;
	for(i=1;i<8;i++)
	{
		Push(&st,i);
	}
	
	printf("栈中元素有:"); 
	StackTraverse(st);
	
	SElemType res;
	Pop(st,&res);
	printf("移除的栈顶元素:%d\n",res);	
	
}

8、获取栈的数据长度

// 获取栈的数据长度
int StackLength(SqStack s) 
{
	return s.top - s.base;
}

测试代码:

void Stack_test(void)
{
	SqStack st;
	InitStack(&st);
	
	int i = 0;
	for(i=1;i<8;i++)
	{
		Push(&st,i);
	}
	
	printf("栈中元素有:"); 
	StackTraverse(st);
	
	int res = StackLength(st);
	printf("当前栈的长度是:%d\n",res);
	
}

9、空栈判断

// 空栈判断
Status StackEmpty(SqStack s)
{
	if(s.top == s.base)
	{
		return TRUE;
	}
	else
	{
		return FALSE;
	}
} 

测试代码:

void Stack_test(void)
{
	SqStack st;
	InitStack(&st);
	
	int i = 0;
	for(i=1;i<8;i++)
	{
		Push(&st,i);
	}
	
	printf("栈中元素有:"); 
	StackTraverse(st);
	
	int res = StackLength(st);
	printf("当前栈的长度是:%d\n",res);
	
	Status res1 = StackEmpty(st);
	if(res1)
	{
		printf("栈为空\n");
	}
	else
	{
		printf("栈不为空\n");
	}
	
}

10、将栈设置为空

// 将栈设置为空
void ClearStack(SqStack *s) 
{
	s->top = s->base;
}

测试代码:

void Stack_test(void)
{
	SqStack st;
	InitStack(&st);
	
	int i = 0;
	for(i=1;i<8;i++)
	{
		Push(&st,i);
	}
	
	printf("栈中元素有:"); 
	StackTraverse(st);
	
	printf("清空栈中数据开始 ---- \n");
	ClearStack(&st);
	printf("清空栈中数据结束 ---- \n");
	
	int len = StackLength(st);
	printf("清空后栈的长度是:%d\n",len); 
	
}

11、销毁栈空间

// 销毁栈空间
void DestoryStack(SqStack *s) 
{
	free(s->base);
	s->top = NULL;
	s->base = NULL;
	s->stacksize = 0;
}

测试代码:

void Stack_test(void)
{
	SqStack st;
	InitStack(&st);
	
	int i = 0;
	for(i=1;i<8;i++)
	{
		Push(&st,i);
	}
	
	printf("栈中元素有:"); 
	StackTraverse(st);
	
	printf("销毁栈空间开始 ---- \n");
	DestoryStack(&st);
	printf("销毁栈空间结束 ---- \n");
	
	int len = StackLength(st);
	printf("清空后栈的长度是:%d\n",len); 
	
}

注意写的所有函数记得在Stack.h中进行声明。

#ifndef _STACK_H
#define _STACK_H

#include "main.h"

#define STACK_INT_SIZE 10  // 栈初始容量为10 
#define STACK_INCREMENT 2  // 空间不够每次增加两个 

// 栈结构类型
typedef struct 
{
	SElemType *base;   // 栈底指针,栈构造和销毁后为NULL
	SElemType *top;   // 栈顶指针
	int stacksize;    // 当前栈的容量,分配的空间数		
}SqStack;

void Stack_test(void);
void InitStack(SqStack *sp) ;
void Push(SqStack *sp,SElemType e);
void StackTraverse(SqStack s);
Status Pop(SqStack s,SElemType *e) ;
int StackLength(SqStack s) ;
Status StackEmpty(SqStack s);
void ClearStack(SqStack *s) ;
void DestoryStack(SqStack *s); 

#endif


http://www.niftyadmin.cn/n/5799799.html

相关文章

Vue3项目中引入TailwindCSS(图文详情)

Vue3项目中引入TailwindCSS&#xff08;图文详细&#xff09; Tailwind CSS 是一个实用工具优先的 CSS 框架&#xff0c;提供丰富的低级类&#xff08;如 text-center、bg-blue-500&#xff09;&#xff0c;允许开发者通过组合这些类快速构建自定义设计&#xff0c;而无需编写…

Nexa AI发布OmniAudio-2.6B:一款快速的音频语言模型,专为边缘部署设计

音频语言模型&#xff08;Audio Language Models&#xff0c;简称ALMs&#xff09;在众多领域扮演着核心角色&#xff0c;涵盖从即时转录与翻译到语音控制界面和辅助技术等应用。然而&#xff0c;现有的解决方案常遭遇如高延迟、计算资源消耗巨大以及对云基础设施的依赖等挑战。…

梯度下降法求六轴机械臂逆向解

梯度下降法求六轴机械臂逆向解 一、几何基础 对于上述六轴机械臂的数学建模来说&#xff0c;可以构建一个六轴机械臂的运动学正逆解的数学模型&#xff0c;在一个直角坐标系中有如下旋转矩阵&#xff1a; 绕x轴旋转 R x ( θ x ) [ 1 0 0 0 cos ⁡ θ x sin ⁡ θ x 0 − …

数据结构(Java版)第六期:LinkedList与链表(一)

目录 一、链表 1.1. 链表的概念及结构 1.2. 链表的实现 专栏&#xff1a;数据结构(Java版) 个人主页&#xff1a;手握风云 一、链表 1.1. 链表的概念及结构 链表是⼀种物理存储结构上⾮连续存储结构&#xff0c;数据元素的逻辑顺序是通过链表中的引⽤链接次序实现的。与火车…

使用iptables+tc实现模拟连续丢包

在上一篇文章中我们介绍了使用linux的tc工具来模拟弱网丢包的能力&#xff0c;介绍了随机丢包&#xff0c;突发丢包&#xff0c;GE模型&#xff0c;组合丢包&#xff0c;但是唯独没有连续丢包的介绍&#xff0c;那是因为tc-netem本身没有模拟连续丢包的能力&#xff0c;需要借助…

gcc和gcc -c区别

gcc 和 gcc -c 之间的主要区别在于编译过程的不同阶段以及最终生成的输出文件类型。理解这两者的区别对于有效地管理和构建项目非常重要。 ### gcc&#xff08;默认行为&#xff09; 当你使用 gcc 编译器而没有指定 -c 选项时&#xff0c;GCC 会执行整个编译链的所有步骤&…

2024年河北省职业院校技能大赛云计算应用赛项赛题第2套(容器云)

#需要资源&#xff08;软件包及镜像&#xff09;或有问题的&#xff0c;可私聊博主&#xff01;&#xff01;&#xff01; #需要资源&#xff08;软件包及镜像&#xff09;或有问题的&#xff0c;可私聊博主&#xff01;&#xff01;&#xff01; #需要资源&#xff08;软件包…

稳定的碰一碰发视频、碰一碰矩阵源码技术开发,支持OEM

一、引言 碰一碰发视频作为一种新兴的信息传递和交互方式&#xff0c;在多个领域展现出了广阔的应用前景&#xff0c;尤其是在商业推广、文化传播、教育等方面。碰一碰矩阵则是对传统碰一碰技术的一种拓展&#xff0c;通过多个碰一碰设备或标签的组合&#xff0c;实现更复杂的功…