Linux C 数据结构——队列

  还是先放这张图,以便对比和理解:

 

   队列是限制在两端进行插入操作和删除操作的线性表,允许进行存入操作的一端称为“队尾”,允许进行删除操作的一端称为“队头”。当线性表中没有元素时,称为“空队”。特点:先进先出(FIFO)。

一、顺序队列
       建立顺序队列结构必须为其静态分配或动态申请一片连续的存储空间,并设置两个指针进行管理。一个是队头指针front,它指向队头元素;另一个是队尾指针rear,它指向下一个入队元素的存储位置,如图所示

     每次在队尾插入一个元素是,rear增1;每次哎队头删除一个元素时,front增1。随着插入和删除操作的进行,队列元素的个数不断变化,队列所占的存储空间也在为队列结构所分配的连续空间中移动。当front=rear时,队列中没有任何元素,称为空队列。当rear增加到指向分配的连续空间之外时,队列无法再插入新元素,但这时往往还有大量可用空间未被占用,这些空间是已经出队的队列元素曾经占用过得存储单元。

    在实际使用队列时,为了使队列空间能重复使用,往往对队列的使用方法稍加改进:无论插入或删除,一旦rear指针增1或front指针增1 时超出了所分配的队列空间,就让它指向这片连续空间的起始位置。自己真从N(MaxSize)增1变到0,可用取余运算rear%N和front%N来实现。这实际上是把队列空间想象成一个环形空间,环形空间中的存储单元循环使用,用这种方法管理的队列也就称为循环队列

    在循环队列中,当队列为空时,有front=rear,而当所有队列空间全占满时,也有front=rear。为了区别这两种情况,规定循环队列最多只能有MaxSize-1个队列元素,当循环队列中只剩下一个空存储单元时,队列就已经满了。因此,队列判空的条件时front=rear,而队列判满的条件时front=(rear+1)%MaxSize。

总结:

1、队头指针front,指向队头元素的位置的前一个位置。即指向预留的位置;

2、队尾指针rear,指向队尾元素的位置;

3、入队: rear = (rear + 1) % N (maxsize),然后元素放入队尾rear所指向的位置;

4、出队: front = (front + 1) % N,然后取出队头指针front所指向的元素;

5、队空: front == rear;

6、队满: (rear + 1) % N == front, N为数组的元素个数;

7、为了区别空队和满队,满队元素个数比数组元素个数少一个。

下面是顺序队列的运算:

   顺序队列也是顺序表的一种,具有顺序表同样的存储结构,由数组定义,配合使用数组下表表示的队头指针和队尾完成各种操作:

[cpp] view plaincopy
  1. #define N 64  //队列中数据元素的数据类型  
  2. typedef int data_t;  
  3. typedef struct  
  4. {  
  5.     data_t data[N]; //用数组作为队列的储存空间  
  6.     int front,rear; //指示队头位置和队尾位置的指针  
  7. }sequeue_t;  

1、创建空队列

[cpp] view plaincopy
  1. sequeue_t *CreateEmptySequeue()  
  2. {  
  3.     sequeue_t *queue;  
  4.     queue = (sequeue_t *)malloc(sizeof(sequeue_t));  
  5.     if (NULL == queue) return NULL;  
  6.       
  7.     queue->front = queue->rear = 0;  
  8.   
  9.     return queue;  
  10. }  

2、摧毁一个队列

[cpp] view plaincopy
  1. void DestroySequeue(sequeue_t *queue)  
  2. {  
  3.     if (NULL != queue)   
  4.     {  
  5.         free(queue);  
  6.     }  
  7. }  

3、判断一个队列是否为空

[cpp] view plaincopy
  1. int EmptySequeue(sequeue_t *queue)  
  2. {  
  3.     if (NULL == queue)   
  4.         return -1;  
  5.   
  6.     return (queue->front == queue->rear ? 1 : 0);  
  7. }  

4、判断一个队列是否为满

[cpp] view plaincopy
  1. int FullSequeue(sequeue_t *queue)  
  2. {  
  3.     if (NULL == queue) return -1;  
  4.   
  5.     return ((queue->rear + 1) % N == queue->front ? 1 : 0);  
  6. }  

5、清空一个队列

[cpp] view plaincopy
  1. void ClearSequeue(sequeue_t *queue)  
  2. {  
  3.     if (NULL == queue) return;  
  4.       
  5.     queue->front = queue->rear = 0;  
  6.   
  7.     return;  
  8. }  

6、入队

[cpp] view plaincopy
  1. int EnQueue(sequeue_t *queue, data_t x)  
  2. {  
  3.     if (NULL == queue) return - 1;  
  4.   
  5.     if (1 == FullSequeue(queue)) return -1; /* full */  
  6.   
  7.     queue->rear = (queue->rear + 1) % N;  
  8.     queue->data[queue->rear] = x;  
  9.   
  10.     return 0;  
  11. }  

7、出队

[cpp] view plaincopy
  1. int DeQueue(sequeue_t *queue, data_t *x)  
  2. {  
  3.     if (NULL == queue) return -1;  
  4.   
  5.     if (1 == EmptySequeue(queue)) return -1; /* empty */  
  6.   
  7.     queue->front = (queue->front + 1) % N;  
  8.   
  9.     if (NULL != x) {  
  10.         *x = queue->data[queue->front];  
  11.     }  
  12.   
  13.     return 0;  
  14. }  


二、链式队列

      用链表表示的队列简称为链队列,如下图所示


一个链队列显然需要两个分别指示队头和队尾的指针(分别成为头指针和尾指针)才能唯一确定。这里,和线性表的单链表一样,为了操作方便起见,我们也给队列添加一个头结点,并令头指针指向头节点。由此,空的链队列的判决条件为头指针和尾指针均指向头结点,如下图所示:

 

链队列的操作记为单链表的插入和删除操作的特殊情况,插入操作在队尾进行,删除操作在队头进行,由队头指针和队尾指针控制队列的操作:

[cpp] view plaincopy
  1. typedef int data_t;  
  2. typedef struct node_t  
  3. {  
  4.     data_t data;  
  5.     struct node_t *next;  
  6. }linknode_t,*linklist_t;  
  7. typedef struct  
  8. {  
  9.     linklist_t front,rear;  
  10. }linkqueue_t;  

1、创建空队列

[cpp] view plaincopy
  1. linkqueue_t *CreateEmptyLinkqueue()  
  2. {  
  3.     linkqueue_t *lp = (linkqueue_t *)malloc(sizeof(linkqueue_t));  
  4.     if(lp == NULL)  
  5.         return;  
  6.   
  7.     lp->front = lp->rear = (linknode_t *)malloc(sizeof(linknode_t));  
  8.     if(lp->front == NULL)  
  9.         return;   
  10.   
  11.     lp->front->next = NULL;  
  12.   
  13.     return lp;  
  14. }  

2、摧毁一个链队列

[cpp] view plaincopy
  1. void DestroyLinkqueue(linkqueue_t *queue)  
  2. {  
  3.     if(queue != NULL)  
  4.     {  
  5.         ClearLinkqueue(queue);  
  6.         free(queue);  
  7.     }  
  8. }  

3、清空一个链队列

[cpp] view plaincopy
  1. void ClearLinkqueue(linkqueue_t *queue)  
  2. {  
  3.     linknode_t *qnode;  
  4.   
  5.     while(q->front)  
  6.     {  
  7.         qnode = queue->front;  
  8.         queue->front= qnode->next;  
  9.         free(qnode);  
  10.     }  
  11.     queue->rear = NULL;}  

4、判断链队列为空

[cpp] view plaincopy
  1. int EmptyLinkqueue(linkqueue_t *queue)  
  2. {  
  3.     if(queue == NULL)  
  4.     return -1;  
  5.       
  6.     return(queue->front == queue->rear ? 1 : 0);  
  7. }  

5、入队

[cpp] view plaincopy
  1. int EnQueue(linkqueue_t *queue,data_t x)  
  2. {  
  3.     linknode_t *node_new;  
  4.     if(queue == NULL)  
  5.         return -1;  
  6.   
  7.     node_new = (linknode_t *)malloc(sizeof(linknode_t));  
  8.     if(node_new == NULL)  
  9.         return -1;  
  10.   
  11.     node_new->data = x;  
  12.     node_new->next = NULL;  
  13.   
  14.     if(queue->front->next == NULL)  
  15.     {  
  16.         queue->front->next = queue->rear = node_new;  
  17.     }  
  18.     else  
  19.     {  
  20.         queue->rear->next = node_new;  
  21.         queue->rear = node_new;  
  22.     }  
  23.     return 0;     
  24. }  

6、出队

[cpp] view plaincopy
  1. int DeQueue(linkqueue_t *queue,data_t *x)  
  2. {  
  3.     linknode_t *node_remove;  
  4.   
  5.     if(queue == NULL || queue->front->next == NULL)  
  6.         return -1;  
  7.   
  8.     node_remove = queue->front->next;  
  9.     queue->front->next = node_remove->next;  
  10.   
  11.     if(x != NULL)  
  12.         *x = node_remove->data;  
  13.   
  14.     free(node_remove);  
  15.   
  16.     return 0;  
  17. }  

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

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

相关文章

如何使用FF的Firebug组件中的net工具查看页面元素加载消耗时间

1.安装FF的Firebug组件:点击FF的Tools的Add-ons菜单,输入Firebug关键字,并选择合适的版本Install。 2.安装完毕后地址栏右边会出现一个小虫图标,右边还有一个下拉箭头。如下图: 3.点击下拉箭头,选择“on fo…

Linux C 数据结构——二叉树

先放这张图: 可以看出,树是非线性结构; 一、树的概念 树(tree)是n(n>0)个节点的有限集合T,它满足两个条件: 1)有且仅有一个特定的称为根(root)的节点&…

Linux C 算法——查找

所谓“查找”记为在一个含有众多的数据元素(或记录)的查找表中找出某个“特定的”数据,即在给定信息集上寻找特定信息元素的过程。 为了便于讨论,必须给出这个“特定的”词的确切含义。首先,引入一个“关键字”的概念&…

SharePoint项目中新建类库的错误处理及项目建设中遇到的问题总结

第一次SP项目总监遇到各种问题,以下是总结:问题1.创建SP项目的时候“场解决方案”跟“沙盒解决方案”是有区别的,具体可以看MSDN官方文档,这里简单摘抄如下:1)场解决方案:承载与W3WP.exe中&…

ECharts学习(1)--简单图表的绘制

1.获取ECharts 官网 下载&#xff1a;http://echarts.baidu.com/download.html 2.在html页面中引入ECharts文件 <!DOCTYPE html> <html><head><meta charset"UTF-8"><title>ECharts练习</title><script type"text/javas…

Linux C 算法——排序

排序(Sort)是将无序的记录序列&#xff08;或称文件&#xff09;调整成有序的序列。 为了方便讨论&#xff0c;在此首先要对排序下一个确切的定义&#xff1a; 假设含有n个记录的序列为 { R1、R2、&#xff0c;。。。Rn } 其相应的关键字序列为 {K1、K2&#xff0c;。。。。Kn}…

JSON.parse 解析json字符串时,遇换行符报错

Json字符串转换成Json对象时候&#xff0c;有两种方式&#xff1a; 假设d是json字符串&#xff1a; 1&#xff0c;eval(( d ))。 2&#xff0c;JSON.parse(d)&#xff1b; 但是以上方式有隐患&#xff0c;如果Json字符串有换行的话&#xff0c;这样转换就会报错。 假如有…

文件I/O和标准I/O的区别

一、先来了解下什么是文件I/O和标准I/O&#xff1a; 文件I/O&#xff1a;文件I/O称之为不带缓存的IO&#xff08;unbuffered I/O)。不带缓存指的是每个read&#xff0c;write都调用内核中的一个系统调用。也就是一般所说的低级I/O——操作系统提供的基本IO服务&#xff0c;与os…

程序集、应用程序配置及App.config和YourSoft.exe.config .

转自&#xff1a;http://www.cnblogs.com/luminji/archive/2010/10/21/1857339.html 什么是程序集 程序集标识属性 强名称的程序集 强名称工作原理配置文件使用 DEVPATH 查找程序集指定要使用的运行库版本Appconfig和YourSoftexeconfig本章概要&#xff1a; 1&#xff1a;什么是…

[Android]在Dagger 2中使用RxJava来进行异步注入(翻译)

以下内容为原创&#xff0c;欢迎转载&#xff0c;转载请注明 来自天天博客&#xff1a;http://www.cnblogs.com/tiantianbyconan/p/6236646.html 在Dagger 2中使用RxJava来进行异步注入 原文&#xff1a;http://frogermcs.github.io/async-injection-in-dagger-2-with-rxjava 几…

关于Go语言在服务端做Restful接口和socket通信

请到我的个人博客看golang rest相关文章 http://xiaorui.cc关于Go语言在服务端做Restful接口和socket通信已经转到: http://xiaorui.cc/2014/10/25/%E5%85%B3%E4%BA%8Ego%E8%AF%AD%E8%A8%80%E5%9C%A8%E6%9C%8D%E5%8A%A1%E7%AB%AF%E5%81%9Arestful%E6%8E%A5%E5%8F%A3%E5%92%8C…

UVa 11136 - Hoax or what

题目大意&#xff1a;超市进行促销活动&#xff0c;顾客可以把账单放到一个箱子里&#xff0c;每天超市会从箱子中抽出最高消费者和最低消费者&#xff0c;最高消费者可以得到&#xff08;最高消费-最低消费&#xff09;的金钱。询问超市在n天的促销活动结束后应支付多少钱。 找…

Winfrom实现圆角设计

主要代码 public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Paint(object sender, PaintEventArgs e) { Type(this, 25, 0.1); } private void…

Linux 系统应用编程——进程基础

一、Linux下多任务机制的介绍 Linux有一特性是多任务&#xff0c;多任务处理是指用户可以在同一时间内运行多个应用程序&#xff0c;每个正在执行的应用程序被称为一个任务。 多任务操作系统使用某种调度(shedule)策略&#xff08;由内核来执行&#xff09;支持多个任务并发执行…

【Python文件处理】递归批处理文件夹子目录内所有txt数据

因为有个需求&#xff0c;需要处理文件夹内所有txt文件&#xff0c;将txt里面的数据筛选&#xff0c;重新存储。 虽然手工可以做&#xff0c;但想到了python一直主张的是自动化测试&#xff0c;就想试着写一个自动化处理数据的程序。 一.分析数据格式 需要处理的数据是txt格式存…

Windows Azure 之服务总线中继服务

Windows Azure的服务总线允许在Web服务内部与外部之间做成一个公共的连接点&#xff0c;在无需更改企业防火墙或者其他安全配置的情况下连接内部和外部的服务 而使用Azure云服务的时候由于缩放的原因通过IP来制定连接也是不科学的&#xff0c;而中继服务则可以充当很好的公共连…

【qt】QT 的信号与槽机制

QT 是一个跨平台的 C GUI 应用构架&#xff0c;它提供了丰富的窗口部件集&#xff0c;具有面向对象、易于扩展、真正的组件编程等特点&#xff0c;更为引人注目的是目前 Linux 上最为流行的 KDE 桌面环境就是建立在 QT 库的基础之上。 QT 支持下列平台&#xff1a;MS/WINDOWS-9…

Linux 系统应用编程——进程间通信(上)

现在再Linux应用较多的进程间通信方式主要有以下几种&#xff1a; 1&#xff09;无名管道&#xff08;pipe&#xff09;及有名管道&#xff08;fifo&#xff09;&#xff1a;无名管道可用于具有亲缘关系进程间的通信&#xff1b;有名管道除具有管道相似的功能外&#xff0c;它还…

通过JDBK操作数据库

一、配置程序——让我们程序能找到数据库的驱动jar包1.把.jar文件复制到项目中去,整合的时候方便。2.在eclipse项目右击“构建路径”--“配置构建路径”--“库”--“添加外部jar”--找到数据库的驱动jar包--点击确定。会在左侧包资源管理器中出现“引用的库”&#xff0c;在里面…