优先队列-数据结构

**本文章使用红色字体来表示重点内容,使用蓝色字体来表示内容可能与其他文章不同点。

**由于有关优先队列的博客比较多,代码不在此文章完成展示。但是代码框架我会讲明白,具体实现各位同学也可以自行完成。

 1.什么是优先队列

(1)队列

        定义:队列是一条先进先出、后进后出的,元素排列成线性的存储结构。

        比如:银行办理业务时排队总是先来的先办理业务。

        队列是没有优先级顺序的,也就是所有的元素都是平等的,无条件遵循先进先出、后进后出的原则。 

(2)优先队列

        定义:优先队列是按照优先级高的元素先出,优先级低的元素后出,无所谓进序的存储结构。

        每次添加一个新的元素时,所有元素都要自觉排序(或者说新添加的元素找到应该存在的位置),使得所有元素按优先级有序。 

        优先队列是线性存储结构,堆排序是排序方法,两者虽然本质上相同,但是是有区别的。没有学习堆排序的同学可以搜索堆排序简单了解。

2.如何实现优先队列

(1)优先队列元素的存储

        方式:优先队列元素的存储是使用顺序表(数组)来存储的。

        我习惯于不使用第一个空间,也就是数组下标为 0 的空间。故从下标为 1 的空间开始存储元素。

        本优先队列采用优先级值越小,优先级越大的方式。若同学们在使用时需要相反可自行调整即可。

        原因在于顺序表的空间连续,可以使用连续空间的关系来建立元素之间的关系

(2)存储中元素的关系

        关系:优先队列中元素关系可以表示成二叉树。

        关系式:① 根节点下标 = 孩子节点下标 / 2

                       ②左孩子节点下标 = 根节点下标 * 2

                       ③右孩子节点下标 = 根节点下标 * 2 + 1

                       ④左孩子节点下标 = 右孩子节点下标 - 1

        为什么我不使用第一个空间,因为这样子关系式比较简便。 

        关系式中下标为数组对应的下标,数组下标都是从 0 开始的,由关系图可以看出元素 5 的下标是 5 ,他的父亲节点元素为 3 下标为 2 。满足下标关系式 ① 2 = 5 / 2 和 ③ 5 = 2 * 2 + 1。其他的同理满足可自行验证。

(3)如何使优先队列中元素有序

        优先队列基本方法:向上筛选,向下筛选。(下面我将称其为上浮操作,下沉操作

        上浮操作:当某个节点比他的父亲节点优先级更高时,要跟父亲节点进行交换。

        下沉操作:当某个节点比它的两个孩子节点优先级更低时,要跟其中的优先级更大的孩子节点交换。(若某个节点只比其中一个孩子优先级更低,则不需要比较孩子节点优先级大小,直接与那个孩子节点交换即可)

        目的:在范围内形成优先级更高元素的处于更靠近二叉树树根的位置。

过程: 

        ①首先假设产生一个无序的数列储存于数组中(第一个空间不使用)。

        ②选择其中一种方案——使用下沉法。需要对每一个有孩子节点的父亲节点进行一遍操作,元素数量为 7 ,故需要对 7 / 2 = 3 开始,对下标为3 2 1三个节点进行操作(因为只有这三个节点有孩子)。

        下沉法操作流程:选中一个父亲节点A,与所有子节点B和C(可能只有一个子节点B而C不存在)进行比较,若存在子节点优先级大于父亲节点,则父亲节点与优先级较大的子节点交换,使其满足父亲节点优先级最高。若发生了交换,则跟随父亲节点A重复操作;若没有发生交换,则结束,寻找下一个父亲节点A'进行操作。操作直到所有父亲节点都进行过一遍结束。

         具体应用流程(数据如图):

        先选中下标为 3 的父亲节点 3 ,与子节点 19 和 16 比较,发现已经满足父亲节点优先级最高,不进行操作。如下图:

         然后选中下标为 2 的父亲节点,与子节点 1 和 9 比较,发现子节点 1 的优先级高于父亲节点 5 高于另一子节点 9 ,故父亲节点 5 和子节点 1 进行交换,并跟随节点 5 重复操作。重复操作发现父亲节点5没有子节点了,不进行操作。如下图:

变为:

         然后选取下标为 1 的父亲节点 14 ,与孩子节点 1 和 3 进行比较,发现孩子节点都比父亲节点优先级高,故选择孩子节点中较高的一个孩子节点 1 ,与父亲节点 14 进行交换。然后跟随父亲节点 14 ,与此时的孩子节点 5 和 9 进行比较,发现又是两个孩子节点优先级较高,故与两个孩子节点其中较高的一个 5 进行交换。然后跟随父亲节点 14 ,发现此时没有孩子节点了,操作结束。如下图:

变为:

变为:

        经过了对所有的父亲节点进行操作,现在满足所有的父亲节点的优先级都大于等于孩子节点。 这样变实现了优先队列中元素逻辑上的有序。

        ③还可以选取上浮法,和下沉法同理,操作相反,需要对所有有父亲节点的节点进行上浮操作,操作过程和下沉法同理,只不过方向发生了改变而已。

(4)如何实现添加和删除元素

        ①入队

        元素的入队:由于元素个数已知,故只需要将元素添加到数组的后一格即可。然后选定此添加元素不断使用上浮法,使其处于优先级合适的位置。

        具体操作流程(如图):

        若需要添加元素 2 ,先将元素放在数组的最尾端。

         然后与父亲节点进行比较,如图节点 2 的优先级高于父亲节点 14 ,故进行交换。

        然后重复操作,节点 2 与父亲节点 5 比较发现需要交换,故进行交换。

        然后重复操作,节点 2 与父亲节点 1 比较发现不需要交换,操作结束。 

       ②出队

         元素的出队:由于元素的个数已知,首先提取出需要出队的元素(即根节点所在的元素,或数组下标为 1 的元素)。然后将出队元素与数组中最后一个末尾元素进行交换,同时抛弃出队元素,然后将末尾元素不断进行下沉法,使末尾元素处于优先级合适的位置。

        具体操作流程(如图):

        首先通过返回值也好或是指针引用等其他方法把需要出队的元素 1 进行保存出队。

        将元素 1 和元素 14 (即根节点元素和末尾元素)进行交换。

        然后舍弃已经出队的元素 1 。

        然后对交换后的元素 14 进行下沉法操作,与两个子孩子进行比较,需要交换,并与优先级高的孩子进行交换。 

        然后重复下沉操作,元素 14 与他的子孩子们进行比较,发现需要交换,并与优先级较高的子孩子 5 进行交换。

        直到发现没有子孩子为止,结束出队操作。 

(5)优先队列的其他操作

        优先队列由于是建立在数组的结构上运行的,故大部分操作都和数组的操作一致。顺序表学习的好的同学们可以简单看一下就能理解了。

        ①初始化

        由队列的初始化可以先建立一个空数组,然后对数组的空间大小赋值初始化,元素个数赋值为 0 。

        ②清除

        只需要将元素个数赋值为 0 即可。

        ③求元素个数

        饭后元素个数。

        ④判断是否为空

        若元素个数为 0 则为空。

        ⑤获得优先队列首元素

        返回数组中下标为 1 的元素。

3.优先队列的用处

(1)有优先级的排队上

        比如当发送信息时,将军发送的信息比其他士兵发送的信息更加重要,需要优先发出,故可以使用优先队列来储存待发出信息。

(2)用于序列排序

        可以把需要排序的元素,按照个人规定的优先级进行排序。只需要先把所有元素给予优先级,然后都入队到优先队列中,最后全部出队,出队顺序就是排序完成后的顺序了。

**由于时间原因,再加上这是本人第一次写博客,可能有一些语言上的不合适,和一些知识上的漏洞。

**如果看完博客的同学有什么疑问,可以留言询问,我会回答并补充博客内容,谢谢。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值