数据结构进阶:使用链表实现栈和队列详解与示例(C, C#, C++)

文章目录

  • 1、 栈与队列简介
    • 栈(Stack)
    • 队列(Queue)
  • 2、使用链表实现栈
    • C语言实现
    • C#语言实现
    • C++语言实现
  • 3、使用链表实现队列
    • C语言实现
    • C#语言实现
    • C++语言实现
  • 4、链表实现栈和队列的性能分析
    • 时间复杂度
    • 空间复杂度
    • 性能特点
    • 与其他实现的比较
  • 总结

在这里插入图片描述


在软件开发中,数据结构是不可或缺的一部分。本文将详细介绍如何使用链表来实现栈和队列这两种基本的数据结构,并提供C、C#和C++三种语言的示例代码。

1、 栈与队列简介

栈(Stack)

栈是一种后进先出(Last In First Out, LIFO)的数据结构。栈的基本操作包括:

  1. push:将元素压入栈顶。
  2. pop:移除栈顶元素。
  3. peek:查看栈顶元素。

队列(Queue)

队列是一种先进先出(First In First Out, FIFO)的数据结构。队列的基本操作包括:

  1. enqueue:在队列尾部添加元素。
  2. dequeue:移除队列头部元素。
  3. peek:查看队列头部元素。

2、使用链表实现栈

链表是一种灵活的数据结构,非常适合实现栈。

C语言实现

#include <stdio.h>
#include <stdlib.h>typedef struct Node {int data;struct Node* next;
} Node;typedef struct Stack {Node* top;
} Stack;void initStack(Stack* stack) {stack->top = NULL;
}void push(Stack* stack, int data) {Node* newNode = (Node*)malloc(sizeof(Node));newNode->data = data;newNode->next = stack->top;stack->top = newNode;
}int pop(Stack* stack) {if (stack->top == NULL) {printf("栈为空\n");return -1;}Node* temp = stack->top;int data = temp->data;stack->top = stack->top->next;free(temp);return data;
}int peek(Stack* stack) {if (stack->top == NULL) {printf("栈为空\n");return -1;}return stack->top->data;
}void destroyStack(Stack* stack) {while (stack->top != NULL) {Node* temp = stack->top;stack->top = stack->top->next;free(temp);}
}int main() {Stack stack;initStack(&stack);push(&stack, 1);push(&stack, 2);push(&stack, 3);printf("栈顶元素:%d\n", peek(&stack));printf("出栈元素:%d\n", pop(&stack));printf("出栈元素:%d\n", pop(&stack));destroyStack(&stack);return 0;
}

C#语言实现

using System;public class Node {public int Data { get; set; }public Node Next { get; set; }
}public class Stack {private Node top;public void Push(int data) {Node newNode = new Node { Data = data, Next = top };top = newNode;}public int Pop() {if (top == null) {throw new InvalidOperationException("栈为空");}int data = top.Data;top = top.Next;return data;}public int Peek() {if (top == null) {throw new InvalidOperationException("栈为空");}return top.Data;}
}class Program {static void Main() {Stack stack = new Stack();stack.Push(1);stack.Push(2);stack.Push(3);Console.WriteLine("栈顶元素:" + stack.Peek());Console.WriteLine("出栈元素:" + stack.Pop());Console.WriteLine("出栈元素:" + stack.Pop());}
}

C++语言实现

#include <iostream>struct Node {int data;Node* next;
};class Stack {
public:Stack() : top(nullptr) {}~Stack() {while (top != nullptr) {Node* temp = top;top = top->next;delete temp;}}void push(int data) {Node* newNode = new Node{data, top};top = newNode;}int pop() {if (top == nullptr) {throw std::runtime_error("栈为空");}Node* temp = top;int data = temp->data;top = top->next;delete temp;return data;}int peek() const {if (top == nullptr) {throw std::runtime_error("栈为空");}return top->data;}private:Node* top;
};int main() {Stack stack;stack.push(1);stack.push(2);stack.push(3);std::cout << "栈顶元素:" << stack.peek() << std::endl;std::cout << "出栈元素:" << stack.pop() << std::endl;std::cout << "出栈元素:" << stack.pop() << std::endl;return 0;
}

3、使用链表实现队列

队列是另一种常见的数据结构,同样可以通过链表来实现。

C语言实现

#include <stdio.h>
#include <stdlib.h>typedef struct Node {int data;struct Node* next;
} Node;typedef struct Queue {Node* front;Node* rear;
} Queue;void initQueue(Queue* queue) {queue->front = queue->rear = NULL;
}void enqueue(Queue* queue, int data) {Node* newNode = (Node*)malloc(sizeof(Node));newNode->data = data;newNode->next = NULL;if (queue->rear == NULL) {queue->front = queue->rear = newNode;} else {queue->rear->next = newNode;queue->rear = newNode;}
}int dequeue(Queue* queue) {if (queue->front == NULL) {printf("队列为空\n");return -1;}Node* temp = queue->front;int data = temp->data;queue->front = queue->front->next;if (queue->front == NULL) {queue->rear = NULL;}free(temp);return data;
}int peekQueue(Queue* queue) {if (queue->front == NULL) {printf("队列为空\n");return -1;}return queue->front->data;
}void destroyQueue(Queue* queue) {while (queue->front != NULL) {Node* temp = queue->front;queue->front = queue->front->next;free(temp);}queue->rear = NULL;
}int main() {Queue queue;initQueue(&queue);enqueue(&queue, 1);enqueue(&queue, 2);enqueue(&queue, 3);printf("队首元素:%d\n", peekQueue(&queue));printf("出队元素:%d\n", dequeue(&queue));printf("出队元素:%d\n", dequeue(&queue));destroyQueue(&queue);return 0;
}

C#语言实现

using System;public class Node {public int Data { get; set; }public Node Next { get; set; }
}public class Queue {private Node front;private Node rear;public void Enqueue(int data) {Node newNode = new Node { Data = data };if (rear == null) {front = rear = newNode;} else {rear.Next = newNode;rear = newNode;}}public int Dequeue() {if (front == null) {throw new InvalidOperationException("队列为空");}int data = front.Data;front = front.Next;if (front == null) {rear = null;}return data;}public int Peek() {if (front == null) {throw new InvalidOperationException("队列为空");}return front.Data;}
}class Program {static void Main() {Queue queue = new Queue();queue.Enqueue(1);queue.Enqueue(2);queue.Enqueue(3);Console.WriteLine("队首元素:" + queue.Peek());Console.WriteLine("出队元素:" + queue.Dequeue());Console.WriteLine("出队元素:" + queue.Dequeue());}
}

C++语言实现

#include <iostream>struct Node {int data;Node* next;
};class Queue {
public:Queue() : front(nullptr), rear(nullptr) {}~Queue() {while (front != nullptr) {Node* temp = front;front = front->next;delete temp;}}void enqueue(int data) {Node* newNode = new Node{data, nullptr};if (rear == nullptr) {front = rear = newNode;} else {rear->next = newNode;rear = newNode;}}int dequeue() {if (front == nullptr) {throw std::runtime_error("队列为空");}Node* temp = front;int data = temp->data;front = front->next;if (front == nullptr) {rear = nullptr;}delete temp;return data;}int peek() const {if (front == nullptr) {throw std::runtime_error("队列为空");}return front->data;}private:Node* front;Node* rear;
};int main() {Queue queue;queue.enqueue(1);queue.enqueue(2);queue.enqueue(3);std::cout << "队首元素:" << queue.peek() << std::endl;std::cout << "出队元素:" << queue.dequeue() << std::endl;std::cout << "出队元素:" << queue.dequeue() << std::endl;return 0;
}

4、链表实现栈和队列的性能分析

时间复杂度

栈(Stack)

  • push(入栈)操作:O(1)

在链表实现的栈中,每次入栈操作只需要在链表头部插入一个新节点,这是一个常数时间操作。

  • pop(出栈)操作:O(1)

出栈操作涉及移除链表头部的节点,这同样是一个常数时间操作。

  • peek(查看栈顶元素)操作:O(1)

查看栈顶元素只需要返回链表头部的节点值,不需要遍历链表。

队列(Queue)

  • enqueue(入队)操作:O(1)

在链表实现的队列中,每次入队操作通常在链表尾部插入一个新节点,这也是一个常数时间操作。

  • dequeue(出队)操作:O(1)

出队操作涉及移除链表头部的节点,在链表实现的队列中,通常需要保持一个指向链表尾部的指针,以便于在尾部进行插入操作。为了使出队操作达到O(1),我们可以使用双端链表(或两个指针分别指向头部和尾部),这样出队时只需要更新头部指针。

  • peek(查看队首元素)操作:O(1)

与栈类似,查看队首元素只需要返回链表头部的节点值。

空间复杂度

  • 栈和队列:O(n)

链表实现栈和队列的空间复杂度是线性的,其中n是栈或队列中元素的数量。每个元素都需要一个节点来存储。

性能特点

  1. 动态大小:链表实现的栈和队列可以根据需要动态地增长和收缩,不需要预先分配固定大小的存储空间。
  2. 无内存碎片:与数组实现相比,链表实现不会产生内存碎片,因为它们通过指针连接,不需要连续的内存空间。
  3. 插入和删除效率:链表的插入和删除操作不需要移动其他元素,只需改变指针,因此效率较高。
  4. 内存开销:链表实现需要额外的内存来存储节点间的指针,这可能比数组实现需要更多的内存。

与其他实现的比较

与数组实现的栈和队列比较:

  1. 数组实现的栈和队列在内存使用上可能更高效,因为它们不需要额外的指针字段。
  2. 数组实现的栈和队列可能需要预先分配固定大小的空间,这可能导致空间浪费或需要动态扩容,而链表实现则可以更加灵活地处理大小变化。

与平衡二叉搜索树(如AVL树、红黑树)实现的栈和队列比较:

  1. 使用平衡二叉搜索树实现的栈和队列在理论上可以达到O(log n)的时间复杂度,但是这在实际中很少见,因为这种实现过于复杂且在实践中不太必要。

总的来说,链表实现的栈和队列在大多数情况下提供了良好的性能,尤其是在元素数量变化较大或者内存使用需要优化时。然而,具体选择哪种实现方式还需要根据实际应用场景和性能需求来决定。

总结

本文通过C、C#和C++三种不同的编程语言,详细介绍了如何使用链表来实现栈和队列这两种基本的数据结构。每种实现都包括了初始化、添加元素、移除元素、查看顶部元素和销毁数据结构的完整操作。

链表由于其灵活性和动态性,是实现栈和队列的理想选择。通过本文的示例,我们可以看到,虽然不同的语言在语法和细节上有所不同,但核心概念和实现逻辑是相似的。

在实际应用中,理解这些数据结构的实现对于编写高效和可靠的应用程序至关重要。无论是进行算法设计、数据处理还是系统开发,掌握栈和队列的实现都是每个程序员的基本技能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/377916.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

轻量级自适用商城卡密发卡源码(可运营)

一款全开源非常好看的发卡源码。轻量级自适应个人自助发卡简介&#xff0c;这是一款二次开发的发卡平台源码修复原版bug,删除无用的代码。所有文件全部解密&#xff0c;只保留后台版权信息内容。大家放心使用&#xff0c;可以用于商业运营。轻量级自适应个人自助发卡。 源码下…

WSL-Ubuntu20.04训练环境配置

1.YOLOv8训练环境配置 训练环境配置的话就仍然以YOLOv8为例&#xff0c;来说明如何配置深度学习训练环境。这部分内容比较简单&#xff0c;主要是安装miniAnaconda以及安装torch和torchvision. 首先是miniAnaconda的安装(参考官网的教程Miniconda — Anaconda )&#xff0c;执行…

车载视频监控管理方案:无人驾驶出租车安全出行的保障

近日&#xff0c;无人驾驶出租车“萝卜快跑”在武汉开放载人测试成为热门话题。随着科技的飞速发展&#xff0c;无人驾驶技术已逐渐从概念走向现实&#xff0c;特别是在出租车行业中&#xff0c;无人驾驶出租车的推出将为公众提供更为安全、便捷、高效的出行服务。 视频监控技…

【Diffusion学习】【生成式AI】Stable Diffusion、DALL-E、Imagen 背後共同的套路

文章目录 图片生成Framework 需要3个组件&#xff1a;相关论文【Stable Diffusion&#xff0c;DALL-E&#xff0c;Imagen】 具体介绍三个组件1. Text encoder介绍【结论&#xff1a;文字的encoder重要&#xff0c;Diffusion的模型不是很重要&#xff01;】评估指标&#xff1a;…

如何保证数据库和redis的数据一致性

1、简介 在客户端请求数据时&#xff0c;如果能在缓存中命中数据&#xff0c;那就查询缓存&#xff0c;不用在去查询数据库&#xff0c;从而减轻数据库的压力&#xff0c;提高服务器的性能。 2、问题如何保证两者的一致性 先更新数据库在删除缓存 难点&#xff1a;如何保证…

极狐Gitlab使用(1)

目录 续接上篇&#xff1a;极狐Gitlab安装部署-CSDN博客 1. 关闭注册功能 2. 创建群组 3. 创建用户 5. 邀请成员到群组 6. 设置导入导出项目源 7. 通过gitee导入库 8. 通过仓库URL导入 9. 自创建项目 10. 默认分支main的权限 11. 使用普通用户进入自建库 12. 创建用…

为企业提升销售工作效率的工作手机管理系统

在竞争日益激烈的市场环境中&#xff0c;企业的销售团队如同前线战士&#xff0c;其作战效率直接关乎企业的生存与发展。然而&#xff0c;传统销售管理模式下的信息孤岛、沟通不畅、数据混乱等问题&#xff0c;正悄然成为制约销售效率提升的瓶颈。今天&#xff0c;我们为您揭秘…

axios以post方式提交表单形式数据

某些后端框架请求接口必须走form表单提交的那种形式&#xff0c;但前端很少有<form action"接口地址" method"post"></form>这种写法去提交表单数据&#xff0c;所以前端需要用axios模拟一个表单提交接口。 Content-Type 代表发送端&#xff0…

【C++PythonJava】字符处理详细解读_字符_ASCLL码_字母数字转换_算法竞赛_开发语言

文章目录 Beginning1&#xff09;ASCLL 码2&#xff09;大小比较2&#xff09;判断数字字符3&#xff09;字符、数字间的相互转换End Beginning 在 C 中&#xff0c;字符和整数有着密不可分的关系。原因就是在计算机中&#xff0c;字符是以一种较 ASCLL 码的整数存储的。自然&…

抖音短视频矩阵策略揭秘:引爆流量秘籍

在当前的数字化媒体环境中&#xff0c;抖音已经成为全球最受欢迎的短视频平台之一&#xff0c;每日吸引了亿计的用户浏览各类视频内容。因此&#xff0c;对于众多企业与营销专家而言&#xff0c;掌握在抖音平台上实施高效的搜索引擎优化&#xff08;SEO&#xff09;策略和构建有…

SpringBoot之健康监控(Actuator)

1&#xff0c;基本介绍 Spring Actuator 是 Spring Boot 提供的一个扩展模块&#xff0c;用于监控和管理应用程序的生产环境。它通过 HTTP 端点暴露了大量的监控和管理功能&#xff0c;使得开发者可以在运行时查看应用程序的运行状况、配置信息、性能指标等。 主要功能&#…

根据图片快速生成word、wps latex公式

快速生成word、wps公式&#xff1a;https://simpletex.net/ai/latex_ocr

一站式短视频矩阵开发,高效托管!

短视频矩阵系统源码SaaS解决方案提供全面的开发服务&#xff0c;包括可视化视频编辑、矩阵式内容分发托管以及集成的多功能开发支持。 短视频矩阵&#xff1a;引爆您的数字营销革命 短视频矩阵系统是一套多功能集成解决方案&#xff0c;专为提升在短视频平台上的内容创作、管理…

使用jenkins进行自动化部署

记录一下查看的文档和遇到的坑 什么是jenkins Jenkins是一个开源的持续集成&#xff08;CI&#xff09;和持续交付&#xff08;CD&#xff09;工具&#xff0c;主要用于自动化软件开发的各个阶段&#xff0c;包括构建、测试、部署等。 Jenkins基于Java开发&#xff0c;支持与…

vue中el-table单元格复制功能

一、单页面中使用 1.在el-table上绑定单击事件 cell-click“copyText” 或双击事件 cell-dblclick“copyText” 注&#xff1a;cell-dblclick函数有四个参数&#xff0c;分别是row, column, cell, event&#xff1b; row&#xff1a;可看到被其操作单元格所在行的所有的数据&…

CentOS7安装部署git和gitlab

安装Git 在Linux系统中是需要编译源码的&#xff0c;首先下载所需要的依赖&#xff1a; yum install -y curl-devel expat-devel gettext-devel openssl-devel zlib-devel gcc perl-ExtUtils-MakeMaker方法一 下载&#xff1a; wget https://mirrors.edge.kernel.org/pub/s…

c++ primer plus 第16章string 类和标准模板库,16.1.3 使用字符串

c primer plus 第16章string 类和标准模板库,16.1.3 使用字符串 c primer plus 第16章string 类和标准模板库,16.1.3 使用字符串 文章目录 c primer plus 第16章string 类和标准模板库,16.1.3 使用字符串16.1.3 使用字符串程序清单16.3 hangman.cpp 16.1.3 使用字符串 现在&a…

opencv学习:图像视频的读取截取部分图像数据颜色通道提取合并颜色通道边界填充数值计算图像融合

一、计算机眼中的图像 1.图像操作 构成像素点的数字在0~255之间 RGB叫做图像的颜色通道 h500&#xff0c;w500 2.灰度图像 3. 彩色图像 4.图像的读取 5.视频的读取 cv2.VideoCapture()--在OpenCV中&#xff0c;可以使用VideoCapture来读取视频文件&#xff0c;或是摄像头数…

解决网页中的 video 标签在移动端浏览器(如百度访问网页)视频脱离文档流播放问题

问题现象 部分浏览器视频脱离文档流&#xff0c;滚动时&#xff0c;视频是悬浮出来&#xff0c;在顶部播放 解决方案 添加下列属性&#xff0c;可解决大部分浏览器的脱离文档流的问题 <videowebkit-playsinline""playsInlinex5-playsinlinet7-video-player-t…

HTML5+CSS3小实例:纯CSS实现奥运五环

实例:纯CSS实现奥运五环 技术栈:HTML+CSS 效果: 源码: 【HTML】 <!DOCTYPE html> <html lang="zh-CN"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-sca…