算法基础三:分治算法---堆的实现与堆排序

算法基础三:分治算法---堆的实现与堆排序

一、堆的概念及其创建

1、二叉堆的概念

(二叉)堆(heap)数据结构是一个数组对象,它可以被视为是一个几乎完全的二叉树。树中的每一个节点对应于数组中的一个元素,该元素存储了节点的值。该树除了最底层,几乎完全填满了,最底层的填充是从左到右进行的。表示堆的数组A具有两个域:length[A],它表示数组中的元素个数;heap-size[A],它表示存储于A中的堆的元素个数,它们之间具有heap-size[A]<=length[A]的关系。

​ 树的根是A[1],对给定节点的下标i,其父亲的下标PARENT(i),左子树的下标LEFT(i),右子树的下标RIGHT(i)可以直接计算:

PARENT(i)
	return [i/2]
LEFT(i)
	return 2i
RIGHT(i)
	return 2i+1

image-20210923102232857

特点:

  • 父节点总是位于孩子的左边
  • 树的高度为3
  • 下标为4的节点(值为8)的高度为1

2、二叉堆的分类

最大堆和最小堆,两种堆中节点的值都要满足堆的性质,区别在于堆的类型。

①最大堆

​ 在最大堆中,最大堆的性质是对每一个非根节点 i,

A[PARENT(i)] >= A[i]

​ 即节点的值至多为其父亲的值。于是最大堆中的最大元素就存储在根中,而以某节点为根的子树中所含的所有节点值不会大于该节点的值。

②最小堆

​ 最小堆以相反的形式组织,最小堆性质是对每一个非根节点 i,

A[PARENT(i)]<=A[i]

​ 最小堆中的最小元素就是根。

如果只有一个元素,也可以看做一个堆,称为单元素堆。

二、二叉堆性质维护问题描述

1、问题描述

image-20210923104010501

image-20210923104023605

2、伪代码描述

MAX-HEAPIFY(A,i)
	l <- LEFT(i)
	r <-RIGHT(i)
	if l <= heap-size[A] and A[l] > A[i]
		then largest <- l
	else largest <- i
    if r <= heap-size[A] and A[r] > A[largest]
    	then largest <-r
    if largest != i
    	then exchange A[i] <-> A[largest]
    		MAX-HEAPIFY(A,largest)

三、二叉堆创建问题描述

1.问题描述

  • 输入:数组A[1...n]
  • 输出:重排后的数组A[1...n],元素间构成一个堆

2、伪代码描述

利用MAX-HEAPIFY通过自底向上的方式将数组A[1...n]转换成一个最大堆。由于子数组A[(n/2)+1...n]的每一个元素都没有左右孩子,所以都是树的叶子,因此每一个均构成一个单元素堆。过程BUILD-MAX-HEAP检测树种的其余节点并对每个节点运行MAX-HEAPIFY

BUILD-MAX-HEAP(A)
	heap-size[A] <- length[A]
	for i <- (length[A]/2) downto 1
		do MAX-HEAPIFY(A,i)

图例:

image-20210923105553834

image-20210923105533470

image-20210923105542947

四、程序实现

1、Comparable型线性表建立堆(最大/最小)

import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class LinearList {

    //在实际的数组中,下标从零开始。所以会和伪代码有所不同
    public static int left(int i){
        return 2*i+1;
    }

    public static int right(int i){
        return 2*i+2;
    }

    public static int parent(int i){
        if (i%2==1)
            return i/2;
        return i/2-1;
    }

    public static void heapify(List<Comparable> a, int i, int heapSize, Comparator comp){
        int l=left(i),r=right(i),most;
        if (l<heapSize && (comp.compare(a.get(l),a.get(i))>0))
            most = l;
        else
            most = i;
        if (r<heapSize && (comp.compare(a.get(r),a.get(most))>0))
            most = r;
        if (most != i){
            Collections.swap(a,i,most);
            heapify(a,most,heapSize,comp);
        }
    }

    public static void buildHeap(List<Comparable> a,Comparator comp){
        int heapSize = a.size();
        for (int i=heapSize/2;i>=0;i--)
            heapify(a,i,heapSize,comp);
    }
}

2、Greater & Less

import java.util.Comparator;

public class Greater implements Comparator<Comparable> {
    public int compare(Comparable x, Comparable y){
        return x.compareTo(y);
    }
}
import java.util.Comparator;

public class Less implements Comparator<Comparable> {
    @Override
    public int compare(Comparable o1, Comparable o2) {
        return o2.compareTo(o1);
    }
}

3、测试

import java.util.List;
import java.util.Vector;

public class Test {

    public static void main(String[] args) {
        int h[] = {4,1,3,2,16,9,10,14,8,7},i;
        Vector<Integer> H = new Vector<>();
        for (int i1 : h) {
            H.add(new Integer(i1));
        }

        LinearList.buildHeap((List)H,new Greater());
        System.out.println("max heap: ");
        System.out.println(H);

        LinearList.buildHeap((List)H,new Less());
        System.out.println("min heap: ");
        System.out.println(H);
    }

}

五、堆排序

1、算法的描述与分析

image-20210923134315959

图解:

image-20210923134359270

2、程序实现

import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class Sort {
    static public void heapSort(List<Comparable> a, Comparator comp){
        int i ,heapSize=a.size();
        LinearList.buildHeap(a,comp);
        for (i=heapSize-1;i>0;i--){
            Collections.swap(a,0,i);
            heapSize--;
            LinearList.heapify(a,0,heapSize,comp);
        }
    }
}

3、测试

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;

public class TestSort {
    public static void main(String[] args) {
        Integer a[] = {5,1,9,4,6,2,0,3,8,7},i;
        String b[] = {"ChongQing","ShangHai","AoMen","TianJin","BeiJing","XiangGang"};
        Double c[] = {8.5,6.3,1.7,9.2,0.5,2.3,4.1,7.4,5.9,3.7};
        ArrayList<Integer> A = new ArrayList<>();
        Vector<String> B = new Vector<>();
        LinkedList<Double> C = new LinkedList<>();

        for (Integer integer : a) {
            A.add(integer);
        }
        for (String s : b) {
            B.add(s);
        }
        for (Double aDouble : c) {
            C.add(aDouble);
        }

        Sort.heapSort((List) A,new Less());
        Sort.heapSort((List) B,new Less());
        Sort.heapSort((List) C,new Greater());

        System.out.println(A);
        System.out.println(B);
        System.out.println(C);
    }
}
posted @ 2021-09-23 13:32  DarkerG  阅读(446)  评论(0编辑  收藏  举报