上班闲着无聊,一直想着要开始写博客,但又不知道写什么。最近又回顾了下数据结构的知识,那就从数据结构开始吧。

前言

关于C语言结构体的知识以及队列的特性请读者自行了解,此处不做过多解释,嘻嘻。

同时此篇文章仅仅是关于队列的链表实现。

第一步:结构体编写

我们首先分析一下队列的特征:先进先出,队尾插入,队头删除,暂时想到的就这么多。

首先,对于链表的节点结构体的内容,我们首先想到的是它有一个值,还有一个指向下

一个节点的指针(链表相关知识请读者自行了解),那么它的结构体可实现如下:

 typedef struct Qnode{
int data;
struct Qnode *next;
};

映射到图形,其是这样的结构:

接下来,要让这种节点实现队列的特性,我们可以再建立一个结构体,该结构体有一个指向队头节点的指针和一个指向队尾节点的指针,那么它的实现如下:

 typedef struct LQueue{
Qnode *front;
Qnode *rear;
};

其中,front指针指向队头,rear指针指向队尾(注意,该指针是指向Qnode类型的指针)

映射到图形,其是这样的结构:

好了,结构体编写工作到这里就完成了,下面开始下一步工作。

第二步,队列的方法分析及实现

一个队列有哪些方法呢,根据前面提到的特性,首先要有插入和删除的方法,我们可以定义插入操作为入队(书上也是这么说的),删除操作为出队,这两个操作应该是队列里最基本的。接下来,初始化队列的方法也是尤其必要的。然后,为了测试方便,还可以定义一个获取队列的长度,队列是否为空,获取队头元素值,获取队尾元素值以及打印队列所有节点数据的方法。下面是对这些方法的实现。

初始化方法:void initQueue(LQueue *q);

方法描述:将创建的队列结构(通过参数传入该方法)的队头和队尾指针都指向一个动态生成的Qnode节点,代码如下:

 void initQueue(LQueue *q){
q->front = q->rear = (Qnode *)malloc(sizeof(Qnode));
q->front->next = NULL;
}

当创建了一个队列变量,然后调用该方法时:

代码:

     LQueue L;
initQueue(&L);

内存空间如图:

判断队列是否为空方法:int empty(LQueue *t);

该方法很简单,不做过多描述,代码如下:

int empty(LQueue *t){
return t->front->next == t->rear;
}

入队方法:void push(LQueue *t, int x);

方法描述:通过动态生成一个Qnode节点,然后将x赋值给该节点的data值,再将该节点插入到队列中,代码如下:

 void push(LQueue *t, int x){
Qnode *s = (Qnode *)malloc(sizeof(Qnode));
s->data = x;
s->next = NULL;
t->rear->next = s;
t->rear = s;
}

代码解释:

  第2行:动态生成一个Qnode节点,让指针s指向它;

  第3行:将传入的x值赋值给生成的节点(s所指向)的data值;

  第4行:将s所指节点的next指针置为空;

  第5行:将队列的队尾指针的next指针指向s所指节点;

  第6行:再将队尾指针指向s节点,完成push操作。

不懂的读者希望能自行画图帮助理解,其实图一画出来就一目了然了。

出队方法:void pop(LQueue *t);

方法描述:使用该方法时,首先应判断队列是否为空,为空则退出,不进行出队操作。如果队列不空,则首先定义一个Qnode类型指针q,让q指向队头节点的下一个节点(因为队头节点仅作为队头,不存储值),把队头去掉的话,就是头节点啦。然后让队头节点的next指针指向q所指节点的下一个节点,再释放掉q所指节点(q所指节点即为要出队的节点),代码如下:

 void pop(LQueue *t){
if(empty(t)){
cout << "LQueue is empty,can't pop.\n";
return;
}
Qnode *q = t->front->next;
t->front->next = q->next;
free(q);
}

代码解释:

  第2-5行:判断队列是否为空,若为空则打印提示消息后退出,不进行出队操作;

  第6行:定义一个指针q,使其指向队头节点的next指针所指向的节点;(前面已经解释了,其实就是指向队头节点)

  第7行:让队头节点的next指针指向q的next指针所指向的节点;

  第8行:释放掉q所指的节点的内存,完成出队操作;

还是那句话,画图!一步一步理解。

获取队头节点的值方法:int getFront(LQueue *t);

该方法很简单,不做过多描述,代码如下:

 int getFront(LQueue *t){
return t->front->next->data;
}

获取队尾节点的值方法:int getRear(LQueue *t);

该方法很简单,不做过多描述,代码如下: 

 int getRear(LQueue *t){
return t->rear->data;
}

获取队列长度的方法:int getSize(LQueue *t);

方法描述:使用一个指向头结点的指针,不断遍历,每遍历一次,计数器加1,当该指针指向空时,遍历完成,返回该计数器,代码如下:

 int getSize(LQueue *t){
Qnode *q = t->front->next;
int k = ;
while(q){
k++;
q = q->next;
}
return k;
}

代码解释:

  第2行:定义一个指向队头节点的指针q;

  第3行:定义一个计数器k;

  第4-7行:该代码为,当q不指向NULL时,k+1,然后q指向下一个节点,继续循环判断。

  第8行:当循环结束时,返回该计数器k,即为队列的长度。

打印队列所有值方法:void printQueue(LQueue *t);

方法描述,定义一个指向Qnode类型的指针,进行遍历,每遍历一个节点,打印该节点,然后继续遍历下一节点,代码如下:

 void printQueue(LQueue *t){
Qnode *q = t->front->next;
while(q){
cout << q->data << " ";
q = q->next;
}
cout << "\n";
}

该代码比较简单,不做过多解释。

好了,方法至此已全部完成,接下来,就可以通过main函数进行测试了。

第三步:编写main方法测试运行

完整代码如下,亲测可用,希望各位新入坑的朋友多多敲代码练习哦:

 #include <iostream>
using namespace std; typedef struct Qnode{
int data;
struct Qnode *next;
}; typedef struct LQueue{
Qnode *front;
Qnode *rear;
}; void initQueue(LQueue *q){
q->front = q->rear = (Qnode *)malloc(sizeof(Qnode));
q->front->next = NULL;
} int empty(LQueue *t){
return t->front->next == t->rear;
} void push(LQueue *t, int x){
Qnode *s = (Qnode *)malloc(sizeof(Qnode));
s->data = x;
s->next = NULL;
t->rear->next = s;
t->rear = s;
} void pop(LQueue *t){
if(empty(t)){
cout << "LQueue is empty,can't pop.\n";
return;
}
Qnode *q = t->front->next;
t->front->next = q->next;
free(q);
if(t->rear == NULL)
t->rear = t->front;
} int getFront(LQueue *t){
return t->front->next->data;
} int getRear(LQueue *t){
return t->rear->data;
} int getSize(LQueue *t){
Qnode *q = t->front->next;
int k = ;
while(q){
k++;
q = q->next;
}
return k;
} void printQueue(LQueue *t){
Qnode *q = t->front->next;
while(q){
cout << q->data << " ";
q = q->next;
}
cout << "\n";
}
int main(){
LQueue L;
initQueue(&L);
cout << "Push data to Queue...\n";
push(&L,);
push(&L,);
push(&L,);
push(&L,);
push(&L,);
push(&L,);
push(&L,);
push(&L,);
cout << "Push finished.\n";
cout << "You have pushed such data:";
printQueue(&L);
cout << "Pop data out of Queue...\n";
pop(&L);
cout << "Pop finished.\n";
cout << "Now the Queue have such data:";
printQueue(&L);
cout << "Get Queue's front data:" << getFront(&L) << endl;
cout << "Get Queue's rear data:" << getRear(&L) << endl;
cout << "Get Queue's size:" << getSize(&L) << endl;
pop(&L);
pop(&L);
pop(&L);
cout << "After poped 3 times:";
printQueue(&L);
cout << "Judge the Queue is null or not(0 means not null,others means null):" << empty(&L) << endl;
pop(&L);
pop(&L);
pop(&L);
pop(&L);
cout << "After poped 4 times:";
printQueue(&L);
cout << "Judge the Queue is null or not(0 means not null,others means null):" << empty(&L) << endl; return ;
}

人生中的第一篇博客,写的不好还请海涵~~祝大家生活愉快~~

数据结构代码实现之队列的链表实现(C/C++)的更多相关文章

  1. 5 数据结构、栈、队列、链表、list、dict、迷宫问题

    1.什么是数据结构 2.栈:后进先出 1.什么是栈 栈(Stack)是一个数据集合,可以理解为只能在一端进行插入或删除操作的列表.   2.栈的Python实现 stack = [] stack.ap ...

  2. JavaScript 数据结构与算法之美 - 线性表(数组、栈、队列、链表)

    前言 基础知识就像是一座大楼的地基,它决定了我们的技术高度. 我们应该多掌握一些可移值的技术或者再过十几年应该都不会过时的技术,数据结构与算法就是其中之一. 栈.队列.链表.堆 是数据结构与算法中的基 ...

  3. 算法与数据结构(二) 栈与队列的线性和链式表示(Swift版)

    数据结构中的栈与队列还是经常使用的,栈与队列其实就是线性表的一种应用.因为线性队列分为顺序存储和链式存储,所以栈可以分为链栈和顺序栈,队列也可分为顺序队列和链队列.本篇博客其实就是<数据结构之线 ...

  4. php数据结构课程---3、队列(队列实现方法)

    php数据结构课程---3.队列(队列实现方法) 一.总结 一句话总结: 1.数据实现:适用于功能不复杂的情况 2.链表实现:受限链表,只能队头队尾操作:适用于功能复杂情况 1.队列的数组实现注意点? ...

  5. php数据结构课程---7、队列实战

    php数据结构课程---7.队列实战 一.总结 一句话总结: 注意条件:注意循环的条件(比如while循环打印队列元素时),注意if的条件 把问题想清楚:比如链表操作初次插入元素和后面再插,效果是不一 ...

  6. 学习javascript数据结构(一)——栈和队列

    前言 只要你不计较得失,人生还有什么不能想法子克服的. 原文地址:学习javascript数据结构(一)--栈和队列 博主博客地址:Damonare的个人博客 几乎所有的编程语言都原生支持数组类型,因 ...

  7. 经典面试题(二)附答案 算法+数据结构+代码 微软Microsoft、谷歌Google、百度、腾讯

    1.正整数序列Q中的每个元素都至少能被正整数a和b中的一个整除,现给定a和b,需要计算出Q中的前几项, 例如,当a=3,b=5,N=6时,序列为3,5,6,9,10,12 (1).设计一个函数void ...

  8. Java数据结构和算法(二)--队列

    上一篇文章写了栈的相关知识,而本文会讲一下队列 队列是一种特殊的线性表,在尾部插入(入队Enqueue),从头部删除(出队Dequeue),和栈的特性相反,存取数据特点是:FIFO Java中queu ...

  9. 数据结构之双端队列(Deque)

    1,双端队列定义 双端队列:其两端都可以入列和出列的数据结构,如下图所示,队列后面(rear)可以加入和移出数据,队列前面(front)可以加入和移出数据 双端队列操作: deque=Deque() ...

随机推荐

  1. vscode等编辑器正则一键剔除注释的方法

    匹配HTML单行注释: <!--(.*?)--> 匹配HTML多行注释: <!--([\s\S|\r]*?)--> 或者: <!--([\w\W]*?)--> 除了 ...

  2. c语言类型修饰符及内存

    今天来学习一下c语言类型修饰符及内存分布 1.auto int a; 默认在内存 2.register int a; 限制变量定义在寄存器上的修饰符 编译器会尽量安排CPU的寄存器去存放这个a,如果寄 ...

  3. windows环境安装和使用curl与ES交互

    一.下载安装 去官网下载对应版本的包,解压后打开CMD切换到对应目录(我的目录,E:\file\I386)下运行CURL.exe文件, 如果把该CURL.exe文件复制到C:\Windows\Syst ...

  4. 递推DP UVA 1291 Dance Dance Revolution

    题目传送门 题意:给一串跳舞的动作,至少一只脚落到指定的位置,不同的走法有不同的体力消耗,问最小体力消费多少分析:dp[i][j][k] 表示前i个动作,当前状态(j, k)的最小消费,状态转移方程: ...

  5. 把sed当作命令解释器使用

    [root@sishen ~]# vim script.sed #!/bin/sed -f #交换第一列和第二列 s/\([^,]*\),\([^,]*\),\(.*\).*/\2,\1, \3/g ...

  6. NBA15-16赛季半程有感

    2015-2016 新赛季NBA已经开打半程又多了,这半个赛季我们见证了 勇士的三节打卡:骑士的磨合反复:马刺的老骥伏枥: 当然还有窝火的XJBD. 豪哥200W刀签约黄蜂,打出来800W刀的身价,无 ...

  7. 外文翻译 《How we decide》赛场上的四分卫 第四节

    这是第一章的最后一节. 书的导言 本章第一节 本章第二节 本章第三节 制作肥皂剧是非常不易的.整个制作组都要很紧张的工作,每天都要拍摄一些新的事件.新的大转折的剧情需要被想象出来,新的剧本需要被编写, ...

  8. 外文翻译 《How we decide》赛场上的四分卫 第二节

    本书导言翻译 本章第一节 "决定是如何做出来的",关于意识最神秘的问题之一.尽管我们时刻做着决定,但是我们没有感觉到大脑内部的一系列有关进程.NFL球探挑选候选球员的评分表中,决策 ...

  9. Spring注解驱动开发之声明式事务

    前言:现今SpringBoot.SpringCloud技术非常火热,作为Spring之上的框架,他们大量使用到了Spring的一些底层注解.原理,比如@Conditional.@Import.@Ena ...

  10. AJPFX对equals()方法和==异同的比较

    equals()方法是Object类的方法,所有的类都集成了此方法,还有部分类重写了这个方法,我们看一下Object类中关于该方法的的源码: public boolean equals(Object ...