热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

斜堆(三)之Java的实现

概要前面分别通过C和C++实现了斜堆,本章给出斜堆的Java版本。还是那句老话,三种实现的原理一样,择其一了解即可。目录1.斜堆的介绍2.斜堆的基本操作3.斜堆的Java实现(完整源码)4.

 

概要

前面分别通过C和C++实现了斜堆,本章给出斜堆的Java版本。还是那句老话,三种实现的原理一样,择其一了解即可。

目录
1. 斜堆的介绍
2. 斜堆的基本操作
3. 斜堆的Java实现(完整源码)
4. 斜堆的Java测试程序

转载请注明出处:http://www.cnblogs.com/skywang12345/p/3638552.html


更多内容:数据结构与算法系列 目录

 

斜堆的介绍

斜堆(Skew heap)也叫自适应堆(self-adjusting heap),它是左倾堆的一个变种。和左倾堆一样,它通常也用于实现优先队列;作为一种自适应的左倾堆,它的合并操作的时间复杂度也是O(lg n)。
它与左倾堆的差别是:
(01) 斜堆的节点没有"零距离"这个属性,而左倾堆则有。
(02) 斜堆的合并操作和左倾堆的合并操作算法不同。

斜堆的合并操作
(01) 如果一个空斜堆与一个非空斜堆合并,返回非空斜堆。
(02) 如果两个斜堆都非空,那么比较两个根节点,取较小堆的根节点为新的根节点。将"较小堆的根节点的右孩子"和"较大堆"进行合并。
(03) 合并后,交换新堆根节点的左孩子和右孩子。
        第(03)步是斜堆和左倾堆的合并操作差别的关键所在,如果是左倾堆,则合并后要比较左右孩子的零距离大小,若右孩子的零距离 > 左孩子的零距离,则交换左右孩子;最后,在设置根的零距离。

 

斜堆的基本操作

1. 基本定义

public class SkewHeapextends Comparable> {

private SkewNode mRoot; // 根结点

private class SkewNodeextends Comparable> {
T key;
// 关键字(键值)
SkewNode left; // 左孩子
SkewNode right; // 右孩子

public SkewNode(T key, SkewNode left, SkewNode right) {
this.key = key;
this.left = left;
this.right = right;
}

public String toString() {
return "key:"+key;
}
}

...
}

SkewNode是斜堆对应的节点类。
SkewHeap是斜堆类,它包含了斜堆的根节点,以及斜堆的操作。

 

2. 合并

/*
* 合并"斜堆x"和"斜堆y"
*/
private SkewNode merge(SkewNode x, SkewNode y) {
if(x == null) return y;
if(y == null) return x;

// 合并x和y时,将x作为合并后的树的根;
// 这里的操作是保证: x的key
if(x.key.compareTo(y.key) > 0) {
SkewNode
tmp = x;
x
= y;
y
= tmp;
}

// 将x的右孩子和y合并,
// 合并后直接交换x的左右孩子,而不需要像左倾堆一样考虑它们的npl。
SkewNode tmp = merge(x.right, y);
x.right
= x.left;
x.left
= tmp;

return x;
}

public void merge(SkewHeap other) {
this.mRoot = merge(this.mRoot, other.mRoot);
}

merge(x, y)是内部接口,作用是合并x和y这两个斜堆,并返回得到的新堆的根节点。
merge(other)是外部接口,作用是将other合并到当前堆中。


3. 添加

/* 
* 新建结点(key),并将其插入到斜堆中
*
* 参数说明:
* key 插入结点的键值
*/
public void insert(T key) {
SkewNode
node = new SkewNode(key,null,null);

// 如果新建结点失败,则返回。
if (node != null)
this.mRoot = merge(this.mRoot, node);
}

insert(key)的作用是新建键值为key的节点,并将其加入到当前斜堆中。

 

4. 删除

/* 
* 删除根结点
*
* 返回值:
* 返回被删除的节点的键值
*/
public T remove() {
if (this.mRoot == null)
return null;

T key
= this.mRoot.key;
SkewNode
l = this.mRoot.left;
SkewNode
r = this.mRoot.right;

this.mRoot = null; // 删除根节点
this.mRoot = merge(l, r); // 合并左右子树

return key;
}

remove()的作用是删除斜堆的最小节点。

 

注意关于斜堆的"前序遍历"、"中序遍历"、"后序遍历"、"打印"、"销毁"等接口就不再单独介绍了。后文的源码中有给出它们的实现代码,Please RTFSC(Read The Fucking Source Code)!

 

斜堆的Java实现(完整源码)

斜堆的实现文件(SkewHeap.java)

  1 /**
2 * Java 语言: 斜堆
3 *
4 * @author skywang
5 * @date 2014/03/31
6 */
7
8 public class SkewHeapextends Comparable> {
9
10 private SkewNode mRoot; // 根结点
11
12 private class SkewNodeextends Comparable> {
13 T key; // 关键字(键值)
14 SkewNode left; // 左孩子
15 SkewNode right; // 右孩子
16
17 public SkewNode(T key, SkewNode left, SkewNode right) {
18 this.key = key;
19 this.left = left;
20 this.right = right;
21 }
22
23 public String toString() {
24 return "key:"+key;
25 }
26 }
27
28 public SkewHeap() {
29 mRoot = null;
30 }
31
32 /*
33 * 前序遍历"斜堆"
34 */
35 private void preOrder(SkewNode heap) {
36 if(heap != null) {
37 System.out.print(heap.key+" ");
38 preOrder(heap.left);
39 preOrder(heap.right);
40 }
41 }
42
43 public void preOrder() {
44 preOrder(mRoot);
45 }
46
47 /*
48 * 中序遍历"斜堆"
49 */
50 private void inOrder(SkewNode heap) {
51 if(heap != null) {
52 inOrder(heap.left);
53 System.out.print(heap.key+" ");
54 inOrder(heap.right);
55 }
56 }
57
58 public void inOrder() {
59 inOrder(mRoot);
60 }
61
62 /*
63 * 后序遍历"斜堆"
64 */
65 private void postOrder(SkewNode heap) {
66 if(heap != null)
67 {
68 postOrder(heap.left);
69 postOrder(heap.right);
70 System.out.print(heap.key+" ");
71 }
72 }
73
74 public void postOrder() {
75 postOrder(mRoot);
76 }
77
78 /*
79 * 合并"斜堆x"和"斜堆y"
80 */
81 private SkewNode merge(SkewNode x, SkewNode y) {
82 if(x == null) return y;
83 if(y == null) return x;
84
85 // 合并x和y时,将x作为合并后的树的根;
86 // 这里的操作是保证: x的key
87 if(x.key.compareTo(y.key) > 0) {
88 SkewNode tmp = x;
89 x = y;
90 y = tmp;
91 }
92
93 // 将x的右孩子和y合并,
94 // 合并后直接交换x的左右孩子,而不需要像左倾堆一样考虑它们的npl。
95 SkewNode tmp = merge(x.right, y);
96 x.right = x.left;
97 x.left = tmp;
98
99 return x;
100 }
101
102 public void merge(SkewHeap other) {
103 this.mRoot = merge(this.mRoot, other.mRoot);
104 }
105
106 /*
107 * 新建结点(key),并将其插入到斜堆中
108 *
109 * 参数说明:
110 * key 插入结点的键值
111 */
112 public void insert(T key) {
113 SkewNode node = new SkewNode(key,null,null);
114
115 // 如果新建结点失败,则返回。
116 if (node != null)
117 this.mRoot = merge(this.mRoot, node);
118 }
119
120 /*
121 * 删除根结点
122 *
123 * 返回值:
124 * 返回被删除的节点的键值
125 */
126 public T remove() {
127 if (this.mRoot == null)
128 return null;
129
130 T key = this.mRoot.key;
131 SkewNode l = this.mRoot.left;
132 SkewNode r = this.mRoot.right;
133
134 this.mRoot = null; // 删除根节点
135 this.mRoot = merge(l, r); // 合并左右子树
136
137 return key;
138 }
139
140 /*
141 * 销毁斜堆
142 */
143 private void destroy(SkewNode heap) {
144 if (heap==null)
145 return ;
146
147 if (heap.left != null)
148 destroy(heap.left);
149 if (heap.right != null)
150 destroy(heap.right);
151
152 heap=null;
153 }
154
155 public void clear() {
156 destroy(mRoot);
157 mRoot = null;
158 }
159
160 /*
161 * 打印"斜堆"
162 *
163 * key -- 节点的键值
164 * direction -- 0,表示该节点是根节点;
165 * -1,表示该节点是它的父结点的左孩子;
166 * 1,表示该节点是它的父结点的右孩子。
167 */
168 private void print(SkewNode heap, T key, int direction) {
169
170 if(heap != null) {
171
172 if(direction==0) // heap是根节点
173 System.out.printf("%2d is root\n", heap.key);
174 else // heap是分支节点
175 System.out.printf("%2d is %2d's %6s child\n", heap.key, key, direction==1?"right" : "left");
176
177 print(heap.left, heap.key, -1);
178 print(heap.right,heap.key, 1);
179 }
180 }
181
182 public void print() {
183 if (mRoot != null)
184 print(mRoot, mRoot.key, 0);
185 }
186 }
View Code

斜堆的测试程序(SkewHeapTest.java)

 1 /**
2 * Java 语言: 斜堆
3 *
4 * @author skywang
5 * @date 2014/03/31
6 */
7
8 public class SkewHeapTest {
9
10 public static void main(String[] args) {
11
12 int a[]= {10,40,24,30,36,20,12,16};
13 int b[]= {17,13,11,15,19,21,23};
14 SkewHeap ha=new SkewHeap();
15 SkewHeap hb=new SkewHeap();
16
17 System.out.printf("== 斜堆(ha)中依次添加: ");
18 for(int i=0; i) {
19 System.out.printf("%d ", a[i]);
20 ha.insert(a[i]);
21 }
22 System.out.printf("\n== 斜堆(ha)的详细信息: \n");
23 ha.print();
24
25
26 System.out.printf("\n== 斜堆(hb)中依次添加: ");
27 for(int i=0; i) {
28 System.out.printf("%d ", b[i]);
29 hb.insert(b[i]);
30 }
31 System.out.printf("\n== 斜堆(hb)的详细信息: \n");
32 hb.print();
33
34 // 将"斜堆hb"合并到"斜堆ha"中。
35 ha.merge(hb);
36 System.out.printf("\n== 合并ha和hb后的详细信息: \n");
37 ha.print();
38 }
39 }
View Code

 

斜堆的Java测试程序

斜堆的测试程序已经包含在它的实现文件(SkewHeapTest.java)中了,这里仅给出它的运行结果:

== 斜堆(ha)中依次添加: 10 40 24 30 36 20 12 16 
== 斜堆(ha)的详细信息:
10 is root
16 is 10's left child
20 is 16's left child
30 is 20's left child
40 is 30's left child
12 is 10's right child
24 is 12's left child
36 is 24's left child

== 斜堆(hb)中依次添加: 17 13 11 15 19 21 23
== 斜堆(hb)的详细信息:
11 is root
13 is 11's left child
17 is 13's left child
23 is 17's left child
19 is 13's right child
15 is 11's right child
21 is 15's left child

== 合并ha和hb后的详细信息:
10 is root
11 is 10's left child
12 is 11's left child
15 is 12's left child
21 is 15's left child
24 is 12's right child
36 is 24's left child
13 is 11's right child
17 is 13's left child
23 is 17's left child
19 is 13's right child
16 is 10's right child
20 is 16's left child
30 is 20's left child
40 is 30's left child

 


推荐阅读
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 如何去除Win7快捷方式的箭头
    本文介绍了如何去除Win7快捷方式的箭头的方法,通过生成一个透明的ico图标并将其命名为Empty.ico,将图标复制到windows目录下,并导入注册表,即可去除箭头。这样做可以改善默认快捷方式的外观,提升桌面整洁度。 ... [详细]
  • Windows下配置PHP5.6的方法及注意事项
    本文介绍了在Windows系统下配置PHP5.6的步骤及注意事项,包括下载PHP5.6、解压并配置IIS、添加模块映射、测试等。同时提供了一些常见问题的解决方法,如下载缺失的msvcr110.dll文件等。通过本文的指导,读者可以轻松地在Windows系统下配置PHP5.6,并解决一些常见的配置问题。 ... [详细]
  • Mac OS 升级到11.2.2 Eclipse打不开了,报错Failed to create the Java Virtual Machine
    本文介绍了在Mac OS升级到11.2.2版本后,使用Eclipse打开时出现报错Failed to create the Java Virtual Machine的问题,并提供了解决方法。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
  • 如何实现织梦DedeCms全站伪静态
    本文介绍了如何通过修改织梦DedeCms源代码来实现全站伪静态,以提高管理和SEO效果。全站伪静态可以避免重复URL的问题,同时通过使用mod_rewrite伪静态模块和.htaccess正则表达式,可以更好地适应搜索引擎的需求。文章还提到了一些相关的技术和工具,如Ubuntu、qt编程、tomcat端口、爬虫、php request根目录等。 ... [详细]
  • 一、Hadoop来历Hadoop的思想来源于Google在做搜索引擎的时候出现一个很大的问题就是这么多网页我如何才能以最快的速度来搜索到,由于这个问题Google发明 ... [详细]
  • VScode格式化文档换行或不换行的设置方法
    本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
  • 基于layUI的图片上传前预览功能的2种实现方式
    本文介绍了基于layUI的图片上传前预览功能的两种实现方式:一种是使用blob+FileReader,另一种是使用layUI自带的参数。通过选择文件后点击文件名,在页面中间弹窗内预览图片。其中,layUI自带的参数实现了图片预览功能。该功能依赖于layUI的上传模块,并使用了blob和FileReader来读取本地文件并获取图像的base64编码。点击文件名时会执行See()函数。摘要长度为169字。 ... [详细]
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
author-avatar
手机用户2602936797
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有