数据结构- 2 栈和队列

栈和队列

1 栈

1.1 定义和逻辑结构

stack:只能在一端进入和删除的线性表,先进后出(FILO)

image-20210623123619000

1.2 存储结构

1.2.1 顺序栈

int stack[maxSize];
int top = -1;          //初始化栈顶指针
x = stack[++top];			 //入栈操作
x = stack[top--];      //出栈操作
top = -1;              //栈空状态
top = maxSize - 1;     //栈满状态

1.2.2 链式栈

image-20210623124741558
//建立一个链式栈
LNode *head = (LNode*)malloc(sizeof(LNode));
head->next = NULL;
LNode *top = NULL;

//元素入栈,将栈顶元素指向头节点并且连在头节点之前
top = (LNode*)malloc(sizeof(LNode));
top->next = NULL;
top->data = 'A';    //同理,如果插入其他的节点,则将此处的A改为其他节点的值
top->next = head->next;
head->next = top;

//元素出栈,也就是删除链表中的元素
x = top->data;
head->next = top->next;
free(top);
top = head->next;

//栈空状态
head->next = NULL;   //此为真,则栈空,只要内存够大,就不存在栈满状态

2 队列

2.1逻辑结构

queue,只可在一端插入,另一端删除的线性表。可插入元素的一端叫队尾(Rear),删除的一端叫队头(Front)。先进先出,FIFO。

2.2存储结构

2.2.1 线性队

image-20210623125848597 image-20210623130454869 image-20210623130635038
int queue[maxSize];
int rear = 0, front = 0;
//根据具体情况推导出队空状态,不仅仅包括 rear = front
//入队操作
queue[++rear] = x;
//出队操作,注意front指针在出队操作完成之后不指向元素,而是指向一个空的内存
x = queue[++front];

//假溢出指的是在rear指针指向数组中最后一个元素时,没有办法进行进一步的插入操作,此时为假溢出
//为了避免假溢出的出现,形象上把整个数组掰弯形成一个环,这在具体的代码中就是取余操作
//“掰弯”之后的入队操作:
rear = (rear+1) % maxSize;
queue[rear] = x;
//“掰弯”之后的出队操作:
front = (front+1) % maxSize;
x = queue[front];

//此时的队空状态:
front == rear 为真
//此时的队满状态:
front == (rear+1) % maxSize 为真

2.2.2 链队

image-20210623131434292 image-20210623131645232
//考试时一般采取的结构体定义方式:
typedef struct{
LNode *front;
LNode *rear;
}queue;

//链队为空的情况:
head->next == NULL为真

3 考点

3.1 输出序列

3.1.1 由出栈序列判断容量

image-20210623132014361

举个例子:具体问答时一般不会直接给出出栈序列,需要根据一些条件进行推测,如下图所示:

1)给出入栈和出栈的顺序,进行判断最大的的存储容量:这种题目的方法就是一个一个地试。

image-20210623132224286 image-20210623132338443

2)给出入栈和出栈的顺序,要求判断哪种出栈是不可能的。这种问题有固定的套路,即如果123,则无312。如果最后一个入栈的第一个出栈,那么整个栈中的出栈顺序就是固定的。

image-20210623132930477 image-20210623133325403

3)Catalan number-只需要记忆

3.2 表达式的转换问题

中缀表达式

前缀表达式(波兰式)

后缀表达式(逆波兰式)

1)中缀转换成前缀或者后缀的方法是给所有的运算参数上加上括号,如果转成前缀,则将括号之间的符号提到两个括号之前。后缀是放在括号之后。

image-20210623134009422 image-20210623134104712 image-20210623134144826 image-20210623134356656

2)前缀后缀转换成中缀

看到两个数字后面紧跟着符号,则将这两个数字括在一起,中间/前面加符号。

image-20210623134547540 image-20210623134802396

3.3 用栈实现表达式的转换

image-20210623135559031

注意中缀转后缀时,新入栈的符号的优先级大于等于栈中的符号的优先级,则出栈。

void infixToPostFix(char infix[], char s2[], int &top2)
{
		char s1[maxSize];
		int top1 = -1;
		int i = 0;
		while(infix[i] != '\0')
		{
		
		//如果扫描到的是数字,则入结果栈
				if('\0' <= infix[i] && infix[i] <= '9')
				{
						s2[++top2] = infix[i];
						++i;
				}   
        
    //如果扫描到的是左括号,则入辅助栈
				else if (infix[i] == ')')
				{
						s1[++top1] = ')';
						--i;							//对应中缀转后缀的--i
				}
				
		//在输入符号的时候,判断符号的优先级
				else if (infix[i] == '+' || infix[i] == '-' || infix[i] == '*' ||infix[i] == '/')
				{
						if (top == -1 || s1[top1] == '(' || getPriority(infix[i]) >= getPriority(s1[top1])) //注意等号
						{
								s1[++top1] = infi[i];
						}
						else
								s2[++top2] = s1[top1--];
        }	
       else if (infix[i] == '(')
       {
       			while (s1[top1] != ')")
       					s2[++top2] = s1[top1--];
       					--top1;
       					--i;          //对应中缀转后缀的--i
       }
		}
		while (top1 != -1)
       			s2[++top2] = s1[top1--];
}

而在中缀转前缀时,新入栈的符号的优先级大于栈中的符号的优先级的时候才出栈,否则继续入栈。

image-20210623140004159
void infixToPostFix(char infix[], char s2[], int &top2)
{
		char s1[maxSize];
		int top1 = -1;
		int i = 0;
		while(infix[i] != '\0')
		{
		
		//如果扫描到的是数字,则入结果栈
				if('\0' <= infix[i] && infix[i] <= '9')
				{
						s2[++top2] = infix[i];
						++i;
				}   
        
    //如果扫描到的是左括号,则入辅助栈
				else if (infix[i] == '(')
				{
						s1[++top1] = '(';
						++i;
				}
				
		//在输入符号的时候,判断符号的优先级
				else if (infix[i] == '+' || infix[i] == '-' || infix[i] == '*' ||infix[i] == '/')
				{
						if (top == -1 || s1[top1] == '(' || getPriority(infix[i]) > getPriority(s1[top1]))
						{
								s1[++top1] = infi[i];
						}
						else
								s2[++top2] = s1[top1--];
        }	
       else if (infix[i] == ')')
       {
       			while (s1[top1] != '(")
       					s2[++top2] = s1[top1--];
       					--top1;
       					++i;
       }
		}
		while (top1 != -1)
       			s2[++top2] = s1[top1--];
}

后缀转前缀的方法是:将数字压入栈中,每两个算式遇到一个符号,则对两个算式进行重新处理,循环往复。

image-20210623140313564

3.4用栈实现表达式求值

3.4.1 中缀表达式

image-20210623143112782

float calInfix(char exp[])
{
		float s1[maxSize]; int top1 = -1;
		char s2[maxSize]; int top2 = -1;
		int i = 0;
		while(exp[i] != '\0')     //遇到串尾,则结束扫描
		{
				if('0' < exp[i] && exp[i] < '9')
				{
						
				//字符转换为数字
						s1[++top1] = exp[i] - '0';    
						++i;
				}
				
				 //左括号直接入字符栈
				else if(exp[i] == '(')          
				{
						s2[++top] = '(';
						++i;
				}
				
				//判断扫描的值是符号
				else if(exp[i] = '+'||exp[i] = '-'||exp[i] = '*'||exp[i] = '/')
				{
						if(top2 == -1 || s2[top2] =='('|| getPriority(exp[i]) > getPriority(s2[top2]) )
						{
								s2[top2] =exp[i];
								++i;
						}
						else 
						{
								int flag = calStackTopTow(s1, top1, s2, top2);
								if(flag == 0)
								return 0;
						}
				else if(exp[i] == ')')
				{
						while(s2[top2] != '(' )
						{
								int flag = calStackTopTow(s1, top1, s2, top2);
								if(flag == 0)
								return 0;
						}
						--top2;
						++i;
				}
				}
				
				 //扫描结束如果栈中还有字符串剩余
				while (top2 != -1) 
				{
			 					int flag = calStackTopTow(s1, top1, s2, top2);
								if(flag == 0)
								return 0;
				}
		}
		return s1[top1];
}
image-20210623144923628

3.4.2 后缀表达式

image-20210623150310134

3.4.3 前缀表达式

从左到右扫描

3.5配置问题

队列的配置是考察的重点

3.5.1正常配置

//假溢出指的是在rear指针指向数组中最后一个元素时,没有办法进行进一步的插入操作,此时为假溢出
//为了避免假溢出的出现,形象上把整个数组掰弯形成一个环,这在具体的代码中就是取余操作
//“掰弯”之后的入队操作:
rear = (rear+1) % maxSize;
queue[rear] = x;
//“掰弯”之后的出队操作:
front = (front+1) % maxSize;
x = queue[front];

//此时的队空状态:
front == rear 为真
//此时的队满状态:
front == (rear+1) % maxSize 为真

计算元素个数的问题

rear>front 时
个数 = rear-front
image-20210623151052495

3.5.2 非正常配置

1)第一种情况

image-20210623151214375 image-20210623151351957 image-20210623151257116 image-20210623151329623

2)第二种情况

image-20210623151638986 image-20210623151652903 image-20210623151605439

3.6扩展问题-双端队列

image-20210623152036663 image-20210623152048896 image-20210623152515686

3.7 栈的扩展内容

3.7.1 共享栈

image-20210623152853812 image-20210623153027880 image-20210623153103795

3.7.2 用栈模拟队列

image-20210623153442779

一定要注意在模拟过程中如果要保证顺序一致,则在移动过程中需要将元素全部移出,否则无法得到一致的顺序。

3.8括号匹配问题

括号匹配:

image-20210623153918606 image-20210623153941384

3.9 利用栈进行计算

image-20210623154117345 image-20210623154150957 image-20210623154212548
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吴哈哈就是我

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值