数据结构:栈和队列

本文详细介绍了栈和队列的基本概念,包括栈的先进后出特性、数组实现的栈和队列操作,以及循环队列的插入与删除策略。重点讲解了栈的创建、初始化、入栈、出栈、获取栈顶元素和判空,以及队列的创建、初始化、入队和出队操作。
摘要由CSDN通过智能技术生成

一丶栈

1.栈的定义

       非常简单,就是先进后出,后进先出的线性表。举个例子,弹夹装子弹,一颗一颗往下摁,然后打出去的时候就是最上面的(最后填充的)子弹。

2.图解

3.栈操作

(1).创建栈结构

typedef int DateType;
typedef struct MyStack {
	DateType* val;  //元素
	int top;    //
	int size;   //容量
}ST;

       这里的top有两种说法:第一,top = 0,那么top就是指向栈顶元素的下一个;第二,top = -1,那么top就指向栈顶元素。两种都行,只是对于后续操作会有些许差异,我用的是第一种。

(2).初始化
void STInit(ST* st)
{
	assert(st);
	st->top = 0;
	st->size = 0;
	st->val = NULL;
}

       全部置为0或NULL。

(3).入栈
void STPush(ST* st, DateType x)  // 入栈
{
	assert(st);
	if (st->top == st->size)   //检查是否栈满
	{
		int newsize = st->size == 0 ? 4 : st->size * 2;  //三目运算符,如果栈容量为0,就给四个单位的容量,其他情况就扩容到原来的两倍
		DateType *newval = (DateType*)realloc(st->val,sizeof(DateType) * newsize); 
 //realloc开辟新空间
		if (newval)   //以防开辟空间失败
		{
			st->val = newval;
			st->size = newsize;
			newval = NULL;
		}
		else
		{
			perror("realloc fail");
			return;
		}
	}
	st->val[st->top++] = x;  //插入元素
}
(4).出栈
DateType STPop(ST* st)  //出栈
{
	assert(st);
	if (st->top > 0)
	{
		return st->val[--st->top];
	}
	return NULL;
}

       前面说了,我的top指向栈顶元素的下一个(其实就是数据长度),所以先减一再元素出栈。这里可能会有一点不理解,我访问的数组下标范围是[0,top-1],此时top == 5,出栈后top == 4,5这个空间还存在,但逻辑上已经被移除,下次入栈就会覆盖5的那个空间。

(5).获取栈顶元素
DateType STTop(ST* st)  //获取栈顶元素
{
	assert(st);
	if (st->top > 0) return st->val[st->top - 1];
	return NULL;
}
(6).判空
int STEmpty(ST* st)  //检查空,空返回1,非空0
{
	assert(st);
	if (st->top > 0) return 0;
	return 1;
}

4.栈补充

       栈可以数组实现也可以链表实现,个人认为数组更简单理解和实现。在程序中,栈应用得最多的就是递归操作。

二丶队列

1.队列的定义

       队列是只允许在一端进行插入操作,另一端删除操作的线性表。简单来说先进先出,后进后出。听名字联想在食堂排队吃饭,一下就理解了。

2.循环队列

       这里的循环队列是用数组实现的,假设此时rear 和 front 是数组下标为0的地方。队列也是可以用链式结构实现的。

插入一个数据后

       此时front == 0,rear == 4,如果rear + 1就会等于5,那么数组就越界了,于是我们每次给rear 和 front 赋值的时候就采用模(取余数)的方法,rear =  (rear + 1)%maxsize(数组最大容量),这样就可以将rear 和 front 的取值控制在[0,maxsize - 1],然后插入一个数据,尾指针(rear)就加1,删除一个数据头指针(front)就加1,如上图图二,当(rear + 1) % maxsize == front {此时就是(4 + 1)% 5 == 0}的时候,此时队列就满了,虽然这个方法多出来了一个单位的空间,但是如果有上万个甚至上亿个数据,这多出来的就可以忽略不计。至于队空,如果一直出队操作,front最终会和rear相遇,此时front == rear,这就是队空。

3.队列的操作(循环队列)

(1).创建队列结构

typedef int SQDataType;
#define maxsize 5
typedef struct SqQueue {
	SQDataType arr[maxsize];
	int rear;  //尾
	int front;  //头
}SQ;

         依旧可以用上面栈讲的扩容方法,这里就只讲思路了。

(2).初始化

void SQInit(SQ* sq)
{
	sq->front = sq->rear = 0;
}

(3).入队

void EnQueue(SQ* sq, SQDataType x)  //入队
{
	if ((sq->rear + 1) % maxsize == sq->front)  //队满
	{
		printf("队满");
		return;
	}
	sq->arr[sq->rear] = x;
	sq->rear = (sq->rear + 1) % maxsize;
}

(4).出队

int DeQueue(SQ* sq)  //出队
{
	int temp = 0;
	if (sq->front == sq->rear)
	{
		printf("队空\n");
	}
	temp = sq->arr[sq->front];
	sq->front = (sq->front + 1) % maxsize;
	return temp;
}

  • 21
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值