首页 > 其他分享 >97.【C语言】数据结构之栈

97.【C语言】数据结构之栈

时间:2024-11-14 19:18:46浏览次数:3  
标签:ps 出栈 top 之栈 栈顶 C语言 assert capacity 97

目录

1.基本概念

2.提炼要点

3.概念选择题

4.栈的实现

栈初始化函数

入栈函数

出栈函数和栈顶函数

栈顶函数

栈销毁函数


基本概念参见王爽老师的《汇编语言 第四版》第56和57页

节选一部分

1.基本概念

2.提炼要点

1.定义:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作

2.进行数据插入和删除\操作的一端称为栈顶,另一端称为栈底

3.栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则

4.压栈(push):栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶;出栈(pop):栈的删除操作叫做出栈,出数据也在栈顶

★★5.两种顺序:一边入栈,一边出栈;先入栈后出栈(这里容易出概念选择题)

3.概念选择题

若进栈序列为 1,2,3,4 ,进栈过程中可以出栈,则下列不可能的一个出栈序列是( )
A 1,4,3,2
B 2,3,4,1
C 3,1,4,2
D 3,4,2,1

答案:选C

4.栈的实现

可使用数组或链表

显然用数组更容易实现,数组具有在内存中连续存放的特点,缓存的命中率比链表高!

栈顶插入(STPush函数)

栈初始化函数

void STInit(ST* ps)
{
	assert(ps);
	ps->a = (STDataType*)malloc(sizeof(STDataType) * 4);
	if (ps->a == NULL)
	{
		perror("malloc");
		return;
	}
	ps->capacity = 4;
	ps->top = 0;//top栈顶元素的下一个位置
}

一次性malloc开辟了16个字节(int*4),ps->a存储开辟空间的首地址,定义capacity=4确保之后判断push不越界

初始化时,栈中没有元素,因此ps->top=0;等待push

入栈函数

void STPush(ST* ps, STDataType x)
{
	assert(ps);
	if (ps->top == ps->capacity)
	{
		STDataType* tmp = (STDataType*)realloc(ps->a, sizeof(STDataType) * ps->capacity * 2);
		if (tmp == NULL)
		{
			perror("realloc");
			return;
		}
		ps->a = tmp;
		ps->capacity *= 2;
	}
	ps->a[ps->top] = x;
	ps->top++;
}

先判断是否越界,如果ps->top == ps->capacity,则开辟两倍的空间,将新开辟空间的指针tmp交给ps->a,ps->a[ps->top] = x;以数组的形式访问栈,ps->top++;移向下个要push的位置

出栈函数和栈顶函数

void STPop(ST* ps)
{
	assert(ps);
	assert(!STEmpty(ps));//确保不越界
	ps->top--;
}

出栈直接改变栈指针top

bool STEmpty(ST* ps)
{
	assert(ps);
	return ps->top == 0;
}

如果assert断言通过,返回ps->a[ps->top - 1](指的是压入栈的最后一个元素,即栈顶元素(注意有-1))

	while (!STEmpty(&st))
	{
		printf("%d ", STTop(&st));//必须先访问栈顶元素,严格执行后进先出
		STPop(&st);
	}

ps不为NULL时,返回 ps->top == 0;

则  while (!STEmpty(&st))变成 while (!(ps->top == 0))

注意执行的顺序:先打印栈顶元素,再将其出栈

栈顶函数

STDataType STTop(ST* ps)//访问栈顶元素
{
	assert(ps);
	assert(!STEmpty(ps));//确保不越界
	return ps->a[ps->top - 1];
}

栈销毁函数

void STDestory(ST* ps)
{
	assert(ps);
	free(ps->a);
	ps->a = NULL;
	ps->top = 0;
	ps->capacity = 0;
}

free(ps->a);一次性销毁所有动态开辟的空间

将ps->a=NULL防止野指针,其余参数(top和capacity)置0恢复原样

标签:ps,出栈,top,之栈,栈顶,C语言,assert,capacity,97
From: https://blog.csdn.net/2401_85828611/article/details/143659257

相关文章

  • 代码随想录算法训练营第一天| 704. 二分查找、35.搜索插入位置、27. 移除元素、977.有
    文档讲解:代码随想录视频讲解:代码随想录状态:完成4道题一、数组理论基础数组:连续内存空间,存储类型相同的元素集合,适合读不适合写注意:Python里可以存储不同类型的元素,但刷题时都是按照相同元素去做的相同元素占用存储的空间大小是一样的,下一个元素的位置就确定了数组时间......
  • c语言知识点总结-字符串、思维导图
    字面串、字符串变量、字符串的读写、字符串中字符的访问、函数、字符串处理操作、字符串数组总结。文中链接:CSDNhttps://mp.csdn.net/mp_blog/creation/editor/143772084锦黎pro-CSDN博客锦黎pro擅长c语言知识点总结、思维导图,等方面的知识https://blog.csdn.net/jilipro?......
  • 理解C语言之深入理解指针
    目录一、1.内存和地址1.1内存1.2究竟该如何理解编址2.指针变量和地址2.1取地址操作符(&)2.2指针变量和解引⽤操作符(*)2.2.1指针变量2.2.2如何拆解指针类型2.2.3解引⽤操作符2.3指针变量的⼤⼩3.指针变量类型的意义3.1指针的解引⽤3.2指针+-整数3.3v......
  • C语言:函数递归
    #include<stdio.h>intmain(){ printf("haha\n"); main(); return0;}先来看这段代码,这是最简易的一段递归的代码。当我们打印完haha后会main函数调用自己,这样就会使屏幕一直打印haha,但是会停止,这是为什么呢?因为当我们为main函数在栈区开出的内存被不断使用,最后导致栈溢......
  • C语言之动态内存申请
    动态内存的作用在开发中根据实际需求开辟内存内存申请分类静态内存申请(静态分配)1,在程序编译或运行过程中,按事先规定大小分配内存空间的分配方式,如inta[10];2,必须事先知道所需空间的大小3,分配在栈区或全局变量区,一般以数组形式4,按计划分配特点:在程序运行......
  • C语言编程 1.11 寻找素数对
     #include<stdio.h>#include<math.h>intsushu(longlongn)        {            longlongsqrt_n=sqrt(n);            for(longlongi=2;i<=sqrt_n;i++)                {                 ......
  • 关于我重生到21世纪学C语言这件事——操作符详解
    与诸君共进步!!!还有你,也要加油!文章目录1.操作符的分类2.⼆进制和进制转换3.原码、反码、补码4.移位操作符5.位操作符:&、|、^、~6.单⽬操作符7.逗号表达式8.下标访问[]、函数调⽤()9.结构成员访问操作符10.操作符的属性:优先级、结合性11.表达式求值1.操作......
  • 二分查找(折半查找)函数与非函数写法代码介绍及其优缺点 C语言
    什么是二分查找?二分查找也叫折半查找 在有序的数组中查找目标的方法需要借助中间元素与目标值的比较来逐步缩小范围一直到找到目标元素或者不存在为止查找的步骤↓1确定左右端点的下标值(注:数组下标从0开始)2计算中间下标位置3比较中间下标位置的数组值与目标值的大......
  • 教你如何清楚的分辨c语言各类指针类型定义
       可以这样说,学好了指针,就代表你学好了c语言。c语言中,通过合理的利用指针,可以快速高效的实现各种底层逻辑。下面陈列c语言中的各类指针定义,让大家分辨其中的具体意义。1,指针变量  我们定义一个指针变量p,指向整形变量i。#include<stdio.h>intmain(){int......
  • C语言的结构体
    结构体的基本概念和使用结构体(Struct)是一种用户自定义的数据类型,它允许将不同类型的数据项组合成一个单一的复合数据类型。结构体中的每个成员可以是不同的数据类型,包括基本数据类型、数组、指针,甚至是其他结构体。结构体的使用非常广泛,尤其在需要组织和管理复杂数据时尤为有......