Java语言实现简单的堆排序
直接切入正题。在这里实现一个一维数组的简单堆排序。
文字描述看的头痛,直接看图显得直观一些
第一步:根据堆排序的定义,通过完全二叉树的方式去 实现,先定义一个Node类存放节点信息
class Node{
Integer index; //节点编号 节点编号的作用在第三步中会有体现
Node parent; //父节点
Node left; //左子节点
Node right; //右子节点
Object data; //数据
public Node(){
this.index = -1;
this.parent = null;
this.left = null;
this.right = null;
this.data = null;
}
public Node getParent() {
return parent;
}
public Integer getIndex() {
return index;
}
public void setIndex(Integer index) {
this.index = index;
}
public void setParent(Node parent) {
this.parent = parent;
}
public Node getLeft() {
return left;
}
public void setLeft(Node left) {
this.left = left;
}
public Node getRight() {
return right;
}
public void setRight(Node right) {
this.right = right;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
第二步,初始化二叉树,将数组中的元素放入Node中的data区保存,同时构建每个节点的双亲、左右孩子的关系
//创建一棵树,为每个node节点添加双亲节点和子节点
public static Node[] createTree(Object[] arr){
Node[] tree = new Node[arr.length];
for(int i = 0;i< tree.length;i++) {
tree[i] = new Node();
tree[i].setData(arr[i]);
tree[i].setIndex(i);
if (i != 0) {
tree[i].setParent(tree[(i - 1) / 2]);
if (tree[(i - 1) / 2].getLeft() == null) {
tree[(i - 1) / 2].setLeft(tree[i]);
} else {
tree[(i - 1) / 2].setRight(tree[i]);
}
}
}
return tree;
}
第三步:构造大根堆,调整每个节点的值,使得除叶子节点外的所有节点的data都不小于其左右子节点的data
public static Node[] BigRootHeap(Node[] tree){
int i = tree.length-1;
while(i >=0){
if(tree[i].getLeft() != null){
if(tree[i].getRight() != null){
if(tree[i].getLeft().getData().hashCode() >= tree[i].getRight().getData().hashCode()){
if(tree[i].getData().hashCode() < tree[i].getLeft().getData().hashCode()){
Object temp = tree[i].getData();
tree[i].setData(tree[i].getLeft().getData());
tree[i].getLeft().setData(temp);
/*当前节点和其左孩子交换data后可能会造成其左孩子的data小于它的左右孩子data,
因此,i需要跳转至其左左孩子节点的位置进行重新排序。下同*/
i = tree[i].getRight().getIndex();
}
}else{
if(tree[i].getData().hashCode() < tree[i].getRight().getData().hashCode()) {
Object temp = tree[i].getData();
tree[i].setData(tree[i].getRight().getData());
tree[i].getRight().setData(temp);
i = tree[i].getLeft().getIndex();
}
}
}else{
if(tree[i].getData().hashCode() < tree[i].getLeft().getData().hashCode()){
Object temp = tree[i].getData();
tree[i].setData(tree[i].getLeft().getData());
tree[i].getLeft().setData(temp);
i = tree[i].getLeft().getIndex();
}
}
}else{
}
i--;
}
return tree;
}
对二叉树进行调整,使得最大值放在最后一个节点,第二大值放在倒数第二个节点…以此类推
public static void sortNode(Node[] tree){
int i = tree.length-1;
while(i > 0){
Object temp = tree[i].getData();
tree[i].setData(tree[0].getData());
tree[0].setData(temp);
/*将排好序的节点和它的双亲节点的父子关系置为null(双亲节点.setRight[Left](null)),
如果不这么做,使用BigRootHeap(tree)再对树进行排序时依旧会把排好序的节点data计算在内,
导致始终得不到一颗有序的树*/
if(i % 2 == 0){
tree[i].getParent().setRight(null);
}else{
tree[i].getParent().setLeft(null);
}
BigRootHeap(tree);
i--;
}
//直接将排序内容输出
for(int j= 0;j<tree.length;j++){
System.out.print(tree[j].getData().toString()+" ");
}
System.out.println();
}
运行结果
public static void main(String[] args){
Object[] arr = new Object[]{1,34,54,23,2,3433,12};
sortNode(BigRootHeap(createTree(arr)));
}
1 2 12 23 34 54 3433
新人第一次在csdn上写文章,有啥写的不对的地方或者需要改进烦请大家指出=-=