拔丝芋头的数据结构复习日记---Day2---堆栈、队列

2023-10-29 14:10

本文主要是介绍拔丝芋头的数据结构复习日记---Day2---堆栈、队列,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

< 今日知识点 >

  • 堆栈
  • 队列

·
·
·

—01 堆栈

在这里插入图片描述

1、栈的顺序存储实现

#define MAXSIZE  //储存数据元素的最大个数
typedef struct SNode *Stack;
struct SNode{ElementType Data[MAXSIZE];int top;
};
  • 栈的顺序存储结构通常由一个一维数组和一个记录栈顶元素位置的变量组成
  • 当栈为空时,通常初始化栈顶元素位置变量top为-1

2、栈的操作实现
(1)入栈

void Push(Stack S,ElementType X)
{if(S->top == MAXSIZE-1){printf("堆栈满");return ;}else{S->Data[++(S->top)] = X;return ;}
}

(2) 出栈

ElementType Pop(Stack S)
{if(S->top == -1){printf("堆栈空");return Error;   //ERROR是ElementType的特殊值,标志错误} else {return(S->Data[(S->top)--]);}
}


例子:在这里插入图片描述

-分析:一种比较聪明的方法是使这两个栈分别从数组的两头开始向中间生长,当两个栈的栈顶指针相遇时,就表示两个栈都满了

代码实现:

#define MAXSIZE   <储存数据元素的最大个数>
struct DStack{ElementType Data[MAXSIZE];int top1;int top2;
}S;
//初始化:
S.top==-1;
S.top2==MAXSIZE;

入栈操作:

void Push(struct DStack *S,ElementType item,int tag)
{if(S->top2 - S->top1 == 1){printf("堆栈已满");return ;}if(tag==1)     //对第一个堆栈进行操作S->Data[++(S->top1)] = item;else S->Data[--(S->top2)] = item;
}

出栈操作:

ElementType Pop(struct DStack *S,int tag)
{if(tag==1){if(S->top1==-1) {printf("堆栈1空");return NULL;else return S->Data[(S->top1)--];}else{if(S->top2==MAXSIZE){printf("堆栈2空");return NULL;else return S->Data[(S->top2)++];}
}
  • tag作为区分两个堆栈的标志,取值为1和2

3、堆栈的链式存储实现

typedef struct SNode *Stack;
struct SNode{ElementType *Data;struct SNode *Next;
};
  • 栈的链式存储结构实际上就是一个单链表,叫做栈链。插入和删除操作只能在栈链的栈顶进行。
  • 栈顶指针top应该在链表的哪一头? (应该在链表头的位置

4、栈的链式存储操作:
(1)堆栈初始化(建立空栈)

Stack CreateStack()
{Stack S;S = (Stack)malloc(sizeof(struct SNode));S->Next = NULL;return S;
}
  • 即堆栈的一个头结点,返回指针

(2) 判断堆栈是否为空

int IsEmpty(Stack S)
{return (S->Next == NULL)
  • 判断堆栈是否为空,若为空返回整数1,否则返回0

(3) 入栈

void Push(ElementType item,Stack S)
{struct SNode *TmpCell;TmpCell = (struct SNode*)malloc(sizeof(struct SNode));TmpCell->Element = item;TmpCell->Next = S->Next;S->Next = TmpCell;
}

(4) 出栈

ElementType Pop(Stack S)         
{      //删除并返回栈顶的元素struct SNode *FirstCell;ElementType topItem;if(IsEmpty(S)){printf("堆栈空");return NULL;}else {FirstCell = S->Next;S->Next = FirstCell -> Next;topItem = FirstCell -> Element;free(FirstCell);return topItem;}
}

5、堆栈应用:表达式求值
在这里插入图片描述

中缀表达式求值

基本策略:将中缀表达式转换为后缀表达式 (如何转换?)
观察一个简单例子:2+9 /3 -5 -> 2 9 3 / + 5 -
总结:
1、运算数相对顺序不变
2、运算符号顺序发生改变

  • 需要存储等待中的运算符号
  • 需要将当前运算符号与 等待中 的最后一个运算符 比较

在这里插入图片描述

中缀表达式如何转换为后缀表达式

-----> 从头到尾读取中缀表达式的每个对象,对每个对象按不同的情况处理
1、运算数:直接输出
2、左括号:压入堆栈
3、右括号:将栈顶的运算符弹出并输出,直到遇到左括号(出栈,不输出)
4、运算符:

  • 优先级大于栈顶运算符时,则把它压栈
  • 优先级小于栈顶运算符时,将栈顶运算符弹出并输出。再比较新的栈顶运算符,直到运算符大于栈顶运算符优先级为止,然后将该运算符压栈。
    5、若各对象处理完毕,则把堆栈中存留的运算符一并输出。在这里插入图片描述

·
·
·

—02 队列

1、
在这里插入图片描述

代码:

#define MAXSIZE  <储存数组元素的最大个数>
struct QNode{ElementType Data[MAXSIZE];int front;int rear;
};
typedef struct QNode *Queue;
  • 队列的顺序存储结构通常由一个一维数组和一个记录队列头元素位置的变量以及一个记录队尾元素位置的变量rear组成

2、 循环队列

在这里插入图片描述

思考题:
  • 堆栈空的判别条件是front==rear ,堆栈满的判别条件是(rear+1)%MAXSIZE == 0
  • 出现空、满无法区分的原因:堆栈可能出现的情况有七种,即空,和存在1、2、3、4、5、6个元素,而下标数字只有六种情况,即0~5,所以六个数字情况是无法不重复地表示堆栈的所有情况的,需要寻找新的表示方法

3、队列的操作
(1)入队列

void AddQ(Queue Q,ElementType item)
{ if(Q->rear+1)%MAXSIZE==Q->front){printf("队列满");return ;}Q->rear = (Q->rear+1% MAXSIZE;Q->Data[Q->rear] =item;
}

(2) 出队列

ElementType DeleteQ (Queue Q)
{if(Q->front == Q->rear){printf("队列空");return ERROR;}else{Q->front = (Q->front+1)%MAXSIZE;return Q->Data[Q->front];}
}
- front和rear指针的移动采用 加1取余 法,体现了顺序存储的循环使用特性。

4、队列的链式存储实现

  • 队列的链式存储结构也可以用一个单链表实现。插入和删除操作分别在链表的两头进行;
  • 思考:队列指针front和rear应该分别指向链表的哪一头??
  • (front进行的是删除操作,应该指向链表头,rear进行的是插入操作,应该指向链表尾。因为对front来说,如果指向的是链表尾,那么一旦删除了一个元素,就找不到其他的元素了,即丢失了)
struct Node{ElementType Data;struct Node *Next;
};struct QNode{        //链队列结构 struct Node *rear;         //指向队尾和队头节点struct Node *front;
}typedef struct QNode *Queue;
Queue Q;

在这里插入图片描述

  • 不带头结点的链式队列出队操作的一个示例:
ElementType DeleteQ(Queue Q)
{	struct Node *frontCell;ElementType frontElem;if(Q->front ==NULL){printf("队列空");return ERROR;}frontCell = Q->front;if(Q->front == Q->rear)       //若队列中只有一个元素,删除后 队列置为空Q->front = Q->rear =NULL;else Q->front = Q->front->Next;frontElem = frontCell->Data;free(frontCell);return frontElem;
}

·
·
·
附:文中所有PPT图片均来自中国大学mooc 浙江大学《数据结构》课程!!

这篇关于拔丝芋头的数据结构复习日记---Day2---堆栈、队列的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/301175

相关文章

hdu1180(广搜+优先队列)

此题要求最少到达目标点T的最短时间,所以我选择了广度优先搜索,并且要用到优先队列。 另外此题注意点较多,比如说可以在某个点停留,我wa了好多两次,就是因为忽略了这一点,然后参考了大神的思想,然后经过反复修改才AC的 这是我的代码 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig

6.1.数据结构-c/c++堆详解下篇(堆排序,TopK问题)

上篇:6.1.数据结构-c/c++模拟实现堆上篇(向下,上调整算法,建堆,增删数据)-CSDN博客 本章重点 1.使用堆来完成堆排序 2.使用堆解决TopK问题 目录 一.堆排序 1.1 思路 1.2 代码 1.3 简单测试 二.TopK问题 2.1 思路(求最小): 2.2 C语言代码(手写堆) 2.3 C++代码(使用优先级队列 priority_queue)

poj 3190 优先队列+贪心

题意: 有n头牛,分别给他们挤奶的时间。 然后每头牛挤奶的时候都要在一个stall里面,并且每个stall每次只能占用一头牛。 问最少需要多少个stall,并输出每头牛所在的stall。 e.g 样例: INPUT: 51 102 43 65 84 7 OUTPUT: 412324 HINT: Explanation of the s

poj 2431 poj 3253 优先队列的运用

poj 2431: 题意: 一条路起点为0, 终点为l。 卡车初始时在0点,并且有p升油,假设油箱无限大。 给n个加油站,每个加油站距离终点 l 距离为 x[i],可以加的油量为fuel[i]。 问最少加几次油可以到达终点,若不能到达,输出-1。 解析: 《挑战程序设计竞赛》: “在卡车开往终点的途中,只有在加油站才可以加油。但是,如果认为“在到达加油站i时,就获得了一

poj3750约瑟夫环,循环队列

Description 有N个小孩围成一圈,给他们从1开始依次编号,现指定从第W个开始报数,报到第S个时,该小孩出列,然后从下一个小孩开始报数,仍是报到S个出列,如此重复下去,直到所有的小孩都出列(总人数不足S个时将循环报数),求小孩出列的顺序。 Input 第一行输入小孩的人数N(N<=64) 接下来每行输入一个小孩的名字(人名不超过15个字符) 最后一行输入W,S (W < N),用

《数据结构(C语言版)第二版》第八章-排序(8.3-交换排序、8.4-选择排序)

8.3 交换排序 8.3.1 冒泡排序 【算法特点】 (1) 稳定排序。 (2) 可用于链式存储结构。 (3) 移动记录次数较多,算法平均时间性能比直接插入排序差。当初始记录无序,n较大时, 此算法不宜采用。 #include <stdio.h>#include <stdlib.h>#define MAXSIZE 26typedef int KeyType;typedef char In

POJ2010 贪心优先队列

c头牛,需要选n头(奇数);学校总共有f的资金, 每头牛分数score和学费cost,问合法招生方案中,中间分数(即排名第(n+1)/2)最高的是多少。 n头牛按照先score后cost从小到大排序; 枚举中间score的牛,  预处理左边与右边的最小花费和。 预处理直接优先队列贪心 public class Main {public static voi

Java并发编程之——BlockingQueue(队列)

一、什么是BlockingQueue BlockingQueue即阻塞队列,从阻塞这个词可以看出,在某些情况下对阻塞队列的访问可能会造成阻塞。被阻塞的情况主要有如下两种: 1. 当队列满了的时候进行入队列操作2. 当队列空了的时候进行出队列操作123 因此,当一个线程试图对一个已经满了的队列进行入队列操作时,它将会被阻塞,除非有另一个线程做了出队列操作;同样,当一个线程试图对一个空

【408数据结构】散列 (哈希)知识点集合复习考点题目

苏泽  “弃工从研”的路上很孤独,于是我记下了些许笔记相伴,希望能够帮助到大家    知识点 1. 散列查找 散列查找是一种高效的查找方法,它通过散列函数将关键字映射到数组的一个位置,从而实现快速查找。这种方法的时间复杂度平均为(