数据结构 05 栈和队列

1 栈只在一端(栈顶)进行运算,并非两端

栈是只允许在表的一端(栈顶)进行插入和删除操作的线性表;队列是只允许在表的一端(队尾)进行插入操作,在另一端(队头)进行删除操作的线性表。

所以栈只在一端(栈顶)进行运算,并非两端。

2 循环队列不是以链表指针的方式来实现头尾相接

循环队列的典型实现是基于数组的,通过对数组下标进行特定的运算(如取模)来实现队列的头尾相接,从而重复利用数组空间。

虽然从广义的 "指针" 概念(比如数组下标也可看作一种地址标识),但通常我们所说的用 "指针" 实现,更多是指像链表那样用指针变量来链接节点。

而循环队列一般不用这种链表指针的方式来实现头尾相接,所以这一说法错误,答案选 "×"。

3 队列只允许在一端(队尾)进行插入(增加)操作,在另一端(队头)进行删除(减少)操作

队列是一种 "先进先出"(FIFO)的线性表,只允许在一端(队尾)进行插入(增加)操作,在另一端(队头)进行删除(减少)操作,并非下端和上端既能增加又能减少。

4 当有 n 个元素依次进栈时,合法的出栈序列数目恰好是第 n 个卡特兰数。

5 在单链表表示的链式队列里,队头位于链表的链头位置

队列是 "先进先出" 的线性结构,链式队列中,队头元素是最先进入队列的,在单链表表示的链式队列里,**队头位于链表的链头位置,这样出队(删除队头元素)操作可以直接从链头进行,方便高效;**而队尾位于链尾,用于入队操作。所以用单链表表示的链式队列的队头在链表的链头位置。

6 只有尾指针的循环链队列的入队和出队

以下是用 C 语言实现只有尾指针的循环链队列的入队和出队操作:

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>

// 定义队列节点结构
typedef struct Node {
    int data;
    struct Node *next;
} Node;

// 入队操作
void enQueue(Node **rear, int value) {
    // 创建新节点
    Node *newNode = (Node *)malloc(sizeof(Node));
    if (newNode == NULL) {
        printf("内存分配失败\n");
        exit(1);
    }
    newNode->data = value;

    // 如果队列为空
    if (*rear == NULL) {
        *rear = newNode;
        newNode->next = newNode; // 自己指向自己,形成循环
    } else {
        // 新节点的 next 指向原队头(尾指针的 next 指向队头)
        newNode->next = (*rear)->next;
        // 尾节点的 next 指向新节点
        (*rear)->next = newNode;
        // 尾指针后移到新节点
        *rear = newNode;
    }
}

// 出队操作
int deQueue(Node **rear) {
    // 队列为空的情况
    if (*rear == NULL) {
        printf("队列为空,无法出队\n");
        exit(1);
    }

    Node *front = (*rear)->next; // 队头节点
    int data = front->data;

    // 如果队列中只有一个节点
    if (front == *rear) {
        *rear = NULL;
    } else {
        // 尾指针的 next 指向原队头的下一个节点,即新的队头
        (*rear)->next = front->next;
    }

    free(front);
    return data;
}

// 测试函数
int main() {
    Node *rear = NULL;

    // 入队
    enQueue(&rear, 1);
    enQueue(&rear, 2);
    enQueue(&rear, 3);

    // 出队并打印
    printf("出队元素: %d\n", deQueue(&rear));
    printf("出队元素: %d\n", deQueue(&rear));
    printf("出队元素: %d\n", deQueue(&rear));

    // 再次入队测试
    enQueue(&rear, 4);
    printf("出队元素: %d\n", deQueue(&rear));

    return 0;
}

代码说明

  1. 入队操作(enQueue
    • 首先创建新节点存储要入队的数据。
    • 如果队列为空(尾指针 rearNULL),则新节点的 next 指向自身,尾指针指向新节点,形成只有一个节点的循环队列。
    • 如果队列不为空,新节点的 next 指向原队头(尾指针的 next 指向队头),然后尾节点的 next 指向新节点,最后尾指针后移到新节点。
  2. 出队操作(deQueue
    • 先判断队列是否为空,为空则无法出队。
    • 找到队头节点(尾指针的 next 指向队头),保存队头节点的数据。
    • 如果队列中只有一个节点,出队后队列为空,尾指针置为 NULL
    • 否则,尾指针的 next 指向原队头的下一个节点(即新的队头),然后释放原队头节点的内存,返回其数据。
  3. 测试部分 :在 main 函数中进行入队和出队操作的测试,验证代码的正确性。

7 实现两个共享存储区、栈顶相向增长的顺序栈的入栈和出栈

1. 定义栈结构

cpp 复制代码
#define maxsize 100 // 假设最大容量为 100
typedef struct {
    int data[maxsize]; // 共享的存储数组
    int top1; // 栈 S1 的栈顶指针,初始为 -1
    int top2; // 栈 S2 的栈顶指针,初始为 maxsize
} DoubleStack;

2. 入栈操作

cpp 复制代码
// 入栈操作,stack 为双栈,x 为入栈元素,stackNum 为栈编号(1 表示 S1,2 表示 S2)
int push(DoubleStack *stack, int x, int stackNum) {
    // 检查是否栈满(两个栈顶指针相邻,说明空间用尽)
    if (stack->top1 + 1 == stack->top2) {
        printf("栈满,无法入栈\n");
        return 0;
    }
    if (stackNum == 1) {
        // S1 入栈,栈顶指针上移,元素放入对应位置
        stack->data[++(stack->top1)] = x;
    } else if (stackNum == 2) {
        // S2 入栈,栈顶指针下移,元素放入对应位置
        stack->data[--(stack->top2)] = x;
    } else {
        printf("栈编号错误\n");
        return 0;
    }
    return 1;
}

3. 出栈操作

cpp 复制代码
// 出栈操作,stack 为双栈,x 用于存储出栈元素,stackNum 为栈编号(1 表示 S1,2 表示 S2)
int pop(DoubleStack *stack, int *x, int stackNum) {
    if (stackNum == 1) {
        // 检查 S1 是否为空
        if (stack->top1 == -1) {
            printf("S1 栈空,无法出栈\n");
            return 0;
        }
        // S1 出栈,栈顶指针下移,取出元素
        *x = stack->data[stack->top1--];
    } else if (stackNum == 2) {
        // 检查 S2 是否为空
        if (stack->top2 == maxsize) {
            printf("S2 栈空,无法出栈\n");
            return 0;
        }
        // S2 出栈,栈顶指针上移,取出元素
        *x = stack->data[stack->top2++];
    } else {
        printf("栈编号错误\n");
        return 0;
    }
    return 1;
}

简单解释

  • 入栈 :两个栈 S1S2 栈顶相向,S1 栈顶从存储区起始位置(top1 初始为 -1)向上增长,S2 栈顶从存储区末尾位置(top2 初始为 maxsize)向下增长。入栈时先判断是否栈满(top1 + 1 == top2 表示空间用尽),若不满则根据栈编号,调整对应栈顶指针并放入元素。
  • 出栈:出栈时先判断对应栈是否为空,若不为空则根据栈编号,调整对应栈顶指针并取出元素。
相关推荐
weixin_4462608543 分钟前
AVA-Encoder:面向智能体原生视频表征学习框架
学习·音视频
DeviceHub1 小时前
硬件工程师选型笔记:ALPS SKPMAPE010 与 Tonevee TS-3025 贴片轻触开关 PIN TO PIN 评估指南
笔记
wuyk5551 小时前
3.链表:用指针串联的动态数据结构
c语言·开发语言·数据结构·链表
吃好睡好便好1 小时前
说说口罩的佩戴
学习·生活·口罩
郝学胜-神的一滴1 小时前
干货版《算法导论》17:二叉树核心原理、遍历逻辑与高阶实操全解
数据结构·c++·python·算法·计算机·编程
fīɡЙtīиɡ ℡2 小时前
大模型结构化输出
人工智能·学习
疯狂打码的少年2 小时前
【数据结构】二叉树的性质(五大性质+计算)
数据结构·笔记·算法
Dave1205462 小时前
Day17:Agent Memory高级设计——短期记忆、长期记忆与向量语义记忆
人工智能·学习
小唔w2 小时前
2026年AI培训行业观察:主流学习渠道一览
人工智能·学习
wabs6663 小时前
关于图论【A*算法 | 卡码网127.骑士的攻击的思考】
数据结构·算法·图论·卡码网·广搜的改进版