C语言数据结构之栈与队列的相互实现

C语言数据结构之栈与队列的相互实现

一、栈(Stack)的介绍

1.1 栈的定义

栈(Stack)是一种特殊的线性表,只能在表的一端插入和删除元素,这一端被称为栈顶,另一端被称为栈底。栈是一种后进先出(LIFO, Last In First Out)的数据结构。栈的插入操作叫做入栈(push),删除操作叫做出栈(pop)。

1.2 栈的实现

栈可以用数组或链表来实现。以下是用数组实现栈的代码示例。

#define MAXSIZE 100
typedef struct {
    int data[MAXSIZE];
    int top;    // 栈顶指针
} SqStack;

// 初始化栈
void InitStack(SqStack *s) {
    s->top = -1;
}

// 判断栈是否为空
bool IsEmpty(SqStack *s) {
    return s->top == -1;
}

// 判断栈是否已满
bool IsFull(SqStack *s) {
    return s->top == MAXSIZE - 1;
}

// 入栈操作
void Push(SqStack *s, int e) {
    if (IsFull(s)) {
        printf("Stack is full\n");
        return;
    }
    s->top++;
    s->data[s->top] = e;
}

// 出栈操作
int Pop(SqStack *s) {
    if (IsEmpty(s)) {
        printf("Stack is empty\n");
        return -1;
    }
    int e = s->data[s->top];
    s->top--;
    return e;
}

二、队列(Queue)的介绍

2.1 队列的定义

队列(Queue)也是一种特殊的线性表,只能在表的一端进行插入,另一端进行删除。这一端插入元素的操作叫做入队(enqueue),删除元素的操作叫做出队(dequeue)。队列是一种先进先出(FIFO,First In First Out)的数据结构。

2.2 队列的实现

队列也可以用数组或链表来实现。以下是用数组实现队列的代码示例。

#define MAXSIZE 100
typedef struct {
    int data[MAXSIZE];
    int front, rear;    // 队头和队尾指针
} SqQueue;

// 初始化队列
void InitQueue(SqQueue *q) {
    q->front = q->rear = 0;
}

// 判断队列是否为空
bool IsEmpty(SqQueue *q) {
    return q->front == q->rear;
}

// 判断队列是否已满
bool IsFull(SqQueue *q) {
    return (q->rear + 1) % MAXSIZE == q->front;
}

// 入队操作
void Enqueue(SqQueue *q, int e) {
    if (IsFull(q)) {
        printf("Queue is full\n");
        return;
    }
    q->data[q->rear] = e;
    q->rear = (q->rear + 1) % MAXSIZE;
}

// 出队操作
int Dequeue(SqQueue *q) {
    if (IsEmpty(q)) {
        printf("Queue is empty\n");
        return -1;
    }
    int e = q->data[q->front];
    q->front = (q->front + 1) % MAXSIZE;
    return e;
}

三、栈与队列的相互实现

3.1 栈实现队列

栈实现队列,需要用到两个栈,一个栈作为插入栈(in-stack),另一个栈作为删除栈(out-stack)。元素插入时,先将元素插入插入栈,取出元素时,先将插入栈中的元素全部转移至删除栈中,然后再从删除栈中出栈。如果删除栈中没元素了,就需要将插入栈中的所有元素转移至删除栈中。

以下是用两个栈实现队列的代码示例。

typedef struct {
    SqStack in_stack;   // 插入栈
    SqStack out_stack;  // 删除栈
} MyQueue;

// 初始化队列
void InitMyQueue(MyQueue *q) {
    InitStack(&q->in_stack);
    InitStack(&q->out_stack);
}

// 判断队列是否为空
bool IsEmpty(MyQueue *q) {
    return IsEmpty(&q->in_stack) && IsEmpty(&q->out_stack);
}

// 入队操作
void Enqueue(MyQueue *q, int e) {
    Push(&q->in_stack, e);
}

// 出队操作
int Dequeue(MyQueue *q) {
    if (IsEmpty(q)) {
        printf("Queue is empty\n");
        return -1;
    }
    if (IsEmpty(&q->out_stack)) {
        while (!IsEmpty(&q->in_stack)) {
            int e = Pop(&q->in_stack);
            Push(&q->out_stack, e);
        }
    }
    return Pop(&q->out_stack);
}

3.2 队列实现栈

队列实现栈,需要用到两个队列,一个队列作为主队列(main-queue),另一个队列作为临时队列(temp-queue)。元素入栈时,直接插入主队列,出栈时,将主队列中的元素依次弹出并插入临时队列,直到只剩一个元素,那么这个元素就是要弹出的元素。此时再交换主队列和临时队列的指针即可。

以下是用两个队列实现栈的代码示例。

#define MAXSIZE 100
typedef struct {
    int data[MAXSIZE];
    int front, rear;    // 队头和队尾指针
} SqQueue;

typedef struct {
    SqQueue main_queue; // 主队列
    SqQueue temp_queue; // 临时队列
} MyStack;

// 初始化栈
void InitMyStack(MyStack *s) {
    InitQueue(&s->main_queue);
    InitQueue(&s->temp_queue);
}

// 判断栈是否为空
bool IsEmpty(MyStack *s) {
    return IsEmpty(&s->main_queue);
}

// 入栈操作
void Push(MyStack *s, int e) {
    Enqueue(&s->main_queue, e);
}

// 出栈操作
int Pop(MyStack *s) {
    if (IsEmpty(s)) {
        printf("Stack is empty\n");
        return -1;
    }
    while (s->main_queue.rear - s->main_queue.front > 1) {
        int e = Dequeue(&s->main_queue);
        Enqueue(&s->temp_queue, e);
    }
    int e = Dequeue(&s->main_queue);
    SwapQueue(&s->main_queue, &s->temp_queue);
    return e;
}

四、示例说明

4.1 栈实现队列示例说明

以下是一个栈实现队列的示例说明。

MyQueue q;
InitMyQueue(&q);

Enqueue(&q, 1);
Enqueue(&q, 2);
Enqueue(&q, 3);

printf("%d\n", Dequeue(&q));    // 1
printf("%d\n", Dequeue(&q));    // 2

Enqueue(&q, 4);

printf("%d\n", Dequeue(&q));    // 3
printf("%d\n", Dequeue(&q));    // 4

Dequeue(&q);    // 队列已经为空,再次操作会有提示:Queue is empty

4.2 队列实现栈示例说明

以下是一个队列实现栈的示例说明。

MyStack s;
InitMyStack(&s);

Push(&s, 1);
Push(&s, 2);
Push(&s, 3);

printf("%d\n", Pop(&s));    // 3
printf("%d\n", Pop(&s));    // 2

Push(&s, 4);

printf("%d\n", Pop(&s));    // 4
printf("%d\n", Pop(&s));    // 1

Pop(&s);    // 栈已经为空,再次操作会有提示:Stack is empty

以上示例说明演示了栈与队列的相互实现,在实际的开发过程中,根据具体的需求选择合适的数据结构来实现相关功能。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C语言数据结构之栈与队列的相互实现 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • win2003 补丁 iis 应用程序池 无法启动 进程退出代码是 0xffffffff

    这个问题的解决需要细致地分析和排查,下面是可能的解决方案: 1. 确认IIS相关组件是否安装 在Windows 2003系统中,IIS是作为一个Windows组件来安装的,所以首先需要确认IIS组件是否正常安装。可以在控制面板的“添加或删除程序”->“添加/删除Windows组件”中找到IIS组件,确保它被正确安装。如果没有安装,则需要重新安装IIS或…

    other 2023年6月25日
    00
  • css网站布局实录学习笔记第三部分网页布局与定位

    CSS网站布局实录学习笔记第三部分:网页布局与定位 1. 简介 在本学习笔记的第三部分中,我们将深入研究网页布局与定位的相关概念和技术。网页布局是构建网页结构的关键,而定位则决定了元素在页面中的位置和排列方式。通过学习本部分的内容,您将能够掌握常用的网页布局技巧和定位方法。 2. 网页布局技巧 2.1 流动布局 流动布局是最常见的网页布局方式,它基于文档流的…

    other 2023年7月28日
    00
  • java二叉树面试题详解

    Java二叉树面试题详解 简介 二叉树是一种非常重要的数据结构,常被用于算法设计与面试问答中。本文将详细探讨Java二叉树面试题相关知识以及解决方案。 常见问题 如何构建一个二叉树? 构建二叉树的方法有很多,但最基础的方法是通过节点类来实现。定义一个Node类来表示二叉树的节点,每个节点包括三个属性:value、left和right。其中,value表示节点…

    other 2023年6月27日
    00
  • Android中XUtils3框架使用方法详解(一)

    Android中XUtils3框架使用方法详解(一) 简介 XUtils3是一款在Android开发中常用的开源框架,它提供了许多方便的工具和功能,可以简化开发过程并提高效率。本攻略将详细介绍XUtils3框架的使用方法。 步骤一:导入XUtils3库 首先,我们需要在项目中导入XUtils3库。可以通过以下步骤完成导入: 在项目的build.gradle文…

    other 2023年9月6日
    00
  • mongodbjavaapi操作很全的整理

    MongoDB Java API 操作很全的整理 MongoDB是一个流行的文档数据库,其Java API可以让Java开发者轻松地与MongoDB进行交互。本文将介绍MongoDB Java API的各种操作,包括CRUD操作、索引操作、聚合操作等,帮助Java开发者更好的使用MongoDB。 环境准备 在使用MongoDB Java API之前,需要先准…

    其他 2023年3月29日
    00
  • python3实现TCP协议的简单服务器和客户端案例(分享)

    下面我将为你详细讲解“python3实现TCP协议的简单服务器和客户端案例(分享)”的完整攻略。 简介 在计算机网络中,TCP(传输控制协议)是一种用于在应用层之间进行通信的协议。它可用于通过互联网传输数据。本文将介绍如何使用Python实现TCP协议的简单服务器和客户端。 实现简单的TCP服务器 以下是实现TCP服务器的示例代码: import socke…

    other 2023年6月27日
    00
  • 详解React项目的服务端渲染改造(koa2+webpack3.11)

    详解React项目的服务端渲染改造(koa2+webpack3.11) 1. 概述 本文将介绍如何将一个React项目改造成服务端渲染的形式,并使用Koa2和webpack3.11完成。 服务端渲染的好处是能够提高网站的SEO和首屏渲染速度,并且能够更好地应对一些搜索引擎不友好的单页面应用(SPA)。通过本文,你将掌握如何在一个React项目中加入服务端渲染…

    other 2023年6月27日
    00
  • 功能强大的Android滚动控件RecyclerView

    功能强大的Android滚动控件RecyclerView攻略 介绍 RecyclerView是Android平台上一个功能强大的滚动控件,用于展示大量数据列表。相比于ListView,RecyclerView提供了更高的灵活性和性能优化。本攻略将详细介绍RecyclerView的使用方法和一些常见示例。 步骤 步骤1:添加依赖 在项目的build.gradl…

    other 2023年8月21日
    00
合作推广
合作推广
分享本页
返回顶部