栈和队列的基本概念及操作

一、栈的定义及使用

栈的定义:栈是仅限于在表尾进行插入和删除操作的线性表。我们通常把允许插入和删除的一端称为栈顶,另一端称为栈底,不含任何元素的称为空栈。栈是一种后进先出的线性表,简称(Last In First Out),简称LIFO结构
在这里插入图片描述

二、栈的特性

2.1 地址分布来看:
栈顶地址最低,栈底的地址最高。
2.2栈的特殊之处在于限制了这个线性表的插入与删除位置,它始终只在栈顶进行。这也就使得:栈底是固定的,最先进栈的只能在栈底

三、栈的应用场景

比如四则运算表达式的求值:
比如我们平常所使用的
9+(3-1)*3 +10/2
这就是我们平时所用的表达式。这里在计算机中可以理解为中缀表达式
在计算机就行运算的时候,它就会将这个运算式变为后缀表达式。也称为逆波兰表达式
规则:从左至右遍历中缀表达式的每个数字和符号,若是数字就输出,即成为后缀表达式的一部分,若是符号,则判断其与栈顶符号的优先级,是右括号或优先级低于栈顶符号则栈顶元素依次出栈并输出。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
栈的应用–递归
比如我们通常所使用的那些递归函数,其本质就相当于是栈的操作。,比如斐波那契数列,其就是从栈顶到栈底依次出栈。还有链表的逆序打印,其本质也是栈的入栈与出栈操作,先进的反而后走。
在不改变原链表的情况下逆序打印链表
栈的定义

typedef int  datatype1;
typedef struct Stack {
   
	datatype1* val1;
	int size;
	int capacity;
}Stack;

链表的定义

typedef int datatype;
typedef struct list
{
   
	datatype val;
	struct list* next;
}Node;
typedef Node* LinkNode;

栈的初始化

void init1(Stack* s)
{
   
	assert(s);
	s->val1 = (datatype1*)malloc(sizeof(datatype1) * 5);
	s->capacity = 5;
	s->size = 0;
}

链表的初始化,这个链表是带头结点的,方便操作

LinkNode init()
{
   
	LinkNode pheader = (LinkNode)malloc(sizeof(Node));
	pheader->val = -1;
	pheader->next = NULL;
	return pheader;
}

栈的扩容

void extend(Stack* s)
{
   
	if (s->size == s->capacity)
	{
   
		s->val1 = (datatype1*)realloc(s->val1, sizeof(datatype1) * s->capacity * 2);
		if (s->val1 == NULL)
		{
   
			printf("内存扩容失败\n");
			return;
		}
		s->capacity *= 2;
	}
}

链表内存开辟

LinkNode my_malloc(datatype val)
{
   
	LinkNode newnode = (LinkNode)malloc(sizeof(Node));
	newnode->next = NULL;
	newnode->val = val;
	return newnode;
}

链表的插入,默认的是头插,因为简单才这么插入

void insert(LinkNode pheader, datatype val)
{
   
	if (pheader == NULL)
	{
   
		return;
	}
	LinkNode newnode = my_malloc(val);
	newnode->next = pheader->next;
	pheader->next = newnode;

}

入栈操作

void pushStack(Stack* s, datatype1 num)
{
   
	assert(s);
	extend(s);
	s->val1[s->size++] = num;
}

出栈操作

void popStack(Stack* s)
{
   
	if (is_empty(s))
	{
   
		return;
	}
	else
	{
   
		s->size--;
	}
}

利用递归实现链表逆序打印

void show_bydigit(LinkNode pheader)参数传递是show_bydigit(pheader->next)
{
   
	/*if (pheader)
	{
		show(pheader->next);
		printf("%d\n", pheader->val);
    }
}

利用栈来实现,首先执行入栈操作,将链表有效元素依次压入栈中

void show(LinkNode pheader,Stack *s)
{
   
	
	//这块是让pheader不为空的情况下,先让它入栈,最后再执行出栈,出栈会在后面给出
	while (pheader)
	{
   
		pushStack(s, pheader->val);
		pheader = pheader->next;
	}
	
}

栈的判空操作:

bool is_empty(Stack* s)
{
   
	assert(s);
	if (s->size != 0)
	{
   
		return false;
	}
	return true;
}

利用栈来实现逆序打印操作

void stack_show(Stack* s)
{
   
	//因为在上面已经给出了入栈操作,我们这时可以利用栈的特性先进后出来实现逆序打印
	while (!<
  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值