408数据结构学习笔记——队列

简介: 408数据结构学习笔记——队列

1.队列的基本概念

1.1.队列的定义

队列只允许在一端插入(队头),在另一端删除(队尾)(FIFO)

1.2.队列的基本操作

initQueue(&Q);初始化队列

destroyQueue(&Q);销毁队列

enQueue(&Q, x);入队

deQueue(&Q, x);出队

getHead(Q, &x);取出队头元素

queueEmpty(Q);判断队空

2.队列的顺序存储结构

2.1.队列的初始化

#define maxSize 10
typedef struct{
    //frnot为队头指针,rear为队尾指针
    int front, rear;
    //采用静态数组存放数据
    elemtype data[maxSize];
}sqQueue;
bool initQueue(sqQueue &Q){
    //队头指针和队尾指针都指向0
    Q.rear = 0;
    Q.front = 0;
}
void testQueue(){
    sqQueue Q;
    initQueue(Q);
    //后续操作
}

331a0a165afc4b878ff84b07af2b6f88.png

2.2.判断队空

bool queueEmpty(sqQueue Q){
    //队空时,队头指针和队尾指针都指向0
    if (Q.front == Q.rear) return true;
    else return false;
}

2.3.入队

因为初始化队列的时候,front和rear指针都指向0,因此,需要牺牲一个存储空间,判断队满

bool enQueue(sqQueue &Q, elemType x){
    //队满
    if ((Q.rear + 1) % maxSize == Q.front) return false;
    //在队尾插入x
    Q.data[Q.rear] = x;
    //队尾元素+1取模
    Q.rear = (Q.rear + 1) % maxSize;
    return true;
}

2.4.出队

bool deQueue(sqQueue &Q, elemType &e){
    //队空
    if(Q.rear == Q.front) return false;
    //取出元素
    e = Q.data[Q.front];
    //front指针前移
    Q.front = ((Q.front + 1) % maxSize);
    return true;
}

2.5.获得队头元素

bool getHead(sqQueue &Q, elemType &e){
    //队空
    if (Q.front == Q.rear) return false;
    //取出队头元素
    e = Q.data[front];
    return true;
}

2.6.队列中元素个数

(front + maxSize - rear) % maxSize

2.7.不牺牲一个存储空间的方法

2.7.1.增加size标记位

size标记队内元素个数

队空时,rear = front && size = 0;队满时,rear = front && size = maxSize。

typedef struct{
    //增加一个size,初始化时,size为0;
    int size;
    int front, rear;
    elemType data[maxSize];
}

2.7.2.增加tag标记位

tag标记上一次的操作是删除/插入

插入后,tag = 1;删除后,tag = 0;

typedef struct{
    //增加一个tag,删除后 tag = 0;插入后 tag = 1
    int tag;
    int front, rear;
    elemType data[maxSize];
}

3.队列的链式存储结构

3.1.链表的初始化

//链表
typedef struct linkNode{
    elemType data;
    strutct linkNode *next;
}linkNode;
typedef struct {
    //头尾指针
    linkNode *rear, *front;
}linkQueue;
bool initQueue(linkQueue &Q){
    //初始化时,front和rear都指向头结点
    Q.rear = Q.front = (linkNode*)malloc(sizeof(linkNode));
    if(Q.rear == NULL) return false;
    Q.front->next = NULL;
    return true;
}
void testQueue(){
    linkQueue Q;
    initQueue(Q);
    //后续操作
}

3.2.入队

//带头结点
bool enQueue(linkQueue &Q, elemType e){
    linkNode *s = (linkNode*)malloc(sizeof(linkNode));
    s->data = e;
    s->next = NULL
    //将s插入到rear后
    Q.rear->next = s;
    //rear后移到s
    Q.rear = s;
    return true;
}
//不带头结点
bool enQueue(linkQueue &Q, elemType e){
    linkNode *s = (linkNode*)malloc(sizeof(linkNode));
    s->data = e;
    s->next = NULL;
    //表不为空,直接插入rear之后
    if (Q.rear) {
        Q.rear->next = s;
        Q.rear = s;
    }
    //表空,作为第一个节点,front和rear都指向s
    else {
        Q.rear = s;
        Q.front = s;
    }
    return true;
}

3.3.出队

//带头结点
bool deQueue(linkQueue &Q, elemType &e){
    //队空
    if (Q.rear == Q.front) return false;
    //p标记第一个元素,输出第一个元素的值
    linkNode *p = Q.front->next;
    e = q->data;
    //将p删除队列
    Q.front->next = p->next;
    //p是队列中最后一个元素,则将rear指针指向front
    if (Q.rear == p) Q.rear = Q.front;
    free(p);
    return true;
}
//不带头结点
bool deQueue(linkQueue &Q, elemType &e){
    //队不空
    if (Q.front){
        //取出队头元素的值
        linkNode *temp = Q.front;
        e = Q.front->data;
        //队列只有一个元素
        if (Q.rear == temp) Q.front = Q.rear = NULL;
        //队列元素>=2
        else Q.front = Q.front->next;
        free(temp);
    }
    //队空
    else return false;
}

3.4.链式存储和顺序存储的去别

顺序存储采用数组,静态分配,需要判断队满情况;

顺序存储采用链表,动态分配,不需要判断队满情况

4.双端队列

6072b64ce7c24964b189fd680ae7f83e.png

5.王道课后题

7dbb586270614fcbb01e318a963c00eb.png

#define maxSize 10
typedef struct {
    int tag, front, rear;
    elemtype data[maxSize];
}linkQueue;
//tag = 0为队空;tag = 1为队满
//front初始化为0,指向队头元素;rear初始化为0,指向队尾元素
//入栈
bool enQueue(linkQueue &Q, elemType e){
    //队满
    if (Q.tag && Q.front = Q.rear) return false;
    //存入元素,并且改变rear值
    Q.data[Q.rear] = e;
    Q.rear = (Q.rear + 1) % maxSize;
    //改变rear值之后,front和rear都指向同一个地方,则队满,改变tag
    if (Q.front == Q.rear) Q.tag = 1;
    return true;
}
//出栈
bool deQueue(linkQueue &Q, elemType &e){
    //队空
    if (!Q.tag && Q.front = Q.rear) return false;
    //取出元素,改变rear值
    e = Q.data[Q.front];
    //改变front值之后,front和rear都指向同一个地方,则队空,改变tag
    Q.front = (Q.front + 1) % maxSize;
    if (Q.front == Q.rear) Q.tag = 0;
    return true;
}

bb9a432d85eb475586dd0bffd0ef25c8.png

typedef struct sqQueue{
  int rear, front;
  int data[10];
}sqQueue;
//top初始值为-1
typedef struct sqStack{
  int top;
  int data[10];
}sqStack;
void reverse(sqQueue& Q, sqStack S) {
  //将队列元素按顺序出队,并进栈
  while (Q.rear == Q.front) {
    S.data[++S.top] = Q.data[Q.front];
    Q.front = (Q.front + 1) % maxSize;
  }
  //将栈中元素按顺序出栈,并进队列
  while (S.top == -1) {
    Q.data[Q.rear] = S.data[S.top--];
    Q.rear = (Q.rear + 1) % maxSize;
  }
}

95733a385873474486ca6f6dbdfdec18.png

85db21107f5a45548ca359ff8bdb2715.png

//1.因为空间只增不减,所以要用链式存储结构,方便增加空间
//2.采用带头结点的循环链式存储结构
//队空:rear == front
//队满:rear->next == front
//4.
typedef struct LNode{
    elemType data;
    struct LNode *next;
}LNode;
typedef struct Queue{
    struct LNode *rear, *front;
}Queue;
bool enQueue(QueQue &Q,elemType e){
    if (Q.rear->next == Q.front) {
        申请新空间
    }
    Q.data[Q.rear] = e;
    Q.rear = Q.rear->next;
    return true;
}
bool deQueue(Queue &Q,elemType &e){
    //队空
    if (Q.rear == Q.front) return false;
    e = Q.data[Q.front];
    Q.front = Q.front->next;
    return true;
}


相关文章
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
1037 9
|
8月前
|
前端开发 Java
java实现队列数据结构代码详解
本文详细解析了Java中队列数据结构的实现,包括队列的基本概念、应用场景及代码实现。队列是一种遵循“先进先出”原则的线性结构,支持在队尾插入和队头删除操作。文章介绍了顺序队列与链式队列,并重点分析了循环队列的实现方式以解决溢出问题。通过具体代码示例(如`enqueue`入队和`dequeue`出队),展示了队列的操作逻辑,帮助读者深入理解其工作机制。
264 1
232.用栈实现队列,225. 用队列实现栈
在232题中,通过两个栈(`stIn`和`stOut`)模拟队列的先入先出(FIFO)行为。`push`操作将元素压入`stIn`,`pop`和`peek`操作则通过将`stIn`的元素转移到`stOut`来实现队列的顺序访问。 225题则是利用单个队列(`que`)模拟栈的后入先出(LIFO)特性。通过多次调整队列头部元素的位置,确保弹出顺序符合栈的要求。`top`操作直接返回队列尾部元素,`empty`判断队列是否为空。 两题均仅使用基础数据结构操作,展示了栈与队列之间的转换逻辑。
|
11月前
|
存储 C语言 C++
【C++数据结构——栈与队列】顺序栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现顺序栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 1.初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储
535 77
|
10月前
|
算法 调度 C++
STL——栈和队列和优先队列
通过以上对栈、队列和优先队列的详细解释和示例,希望能帮助读者更好地理解和应用这些重要的数据结构。
245 11
|
10月前
|
DataX
☀☀☀☀☀☀☀有关栈和队列应用的oj题讲解☼☼☼☼☼☼☼
### 简介 本文介绍了三种数据结构的实现方法:用两个队列实现栈、用两个栈实现队列以及设计循环队列。具体思路如下: 1. **用两个队列实现栈**: - 插入元素时,选择非空队列进行插入。 - 移除栈顶元素时,将非空队列中的元素依次转移到另一个队列,直到只剩下一个元素,然后弹出该元素。 - 判空条件为两个队列均为空。 2. **用两个栈实现队列**: - 插入元素时,选择非空栈进行插入。 - 移除队首元素时,将非空栈中的元素依次转移到另一个栈,再将这些元素重新放回原栈以保持顺序。 - 判空条件为两个栈均为空。
|
11月前
|
存储 C++ 索引
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
【数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】初始化队列、销毁队列、判断队列是否为空、进队列、出队列等。本关任务:编写一个程序实现环形队列的基本运算。(6)出队列序列:yzopq2*(5)依次进队列元素:opq2*(6)出队列序列:bcdef。(2)依次进队列元素:abc。(5)依次进队列元素:def。(2)依次进队列元素:xyz。开始你的任务吧,祝你成功!(4)出队一个元素a。(4)出队一个元素x。
444 13
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
|
11月前
|
存储 C语言 C++
【C++数据结构——栈与队列】链栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现链栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储整数,最大
241 9
|
11月前
|
C++
【C++数据结构——栈和队列】括号配对(头歌实践教学平台习题)【合集】
【数据结构——栈和队列】括号配对(头歌实践教学平台习题)【合集】(1)遇到左括号:进栈Push()(2)遇到右括号:若栈顶元素为左括号,则出栈Pop();否则返回false。(3)当遍历表达式结束,且栈为空时,则返回true,否则返回false。本关任务:编写一个程序利用栈判断左、右圆括号是否配对。为了完成本关任务,你需要掌握:栈对括号的处理。(1)遇到左括号:进栈Push()开始你的任务吧,祝你成功!测试输入:(()))
249 7
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
358 5

热门文章

最新文章