日撸 Java 三百行day48

说明

闵老师的文章链接: 日撸 Java 三百行(总述)_minfanphd的博客-优快云博客
自己也把手敲的代码放在了github上维护:https://github.com/fulisha-ok/sampledata

day48 堆排序

1.基本思路

(1)大/小顶堆:每一个结点值都大于(小于)或等于孩子结点(实际上堆可以看成一颗完全二叉树)

(2)堆排序:利用这种堆的结构进行排序。如:对一个待排序列进行堆排序,需要先建堆(大顶堆),这时我们可以结合大顶堆的性质,取堆顶元素,取完堆顶元素后我们要重新调整大顶堆,再取堆顶数据再调整。在这个过程会涉及建堆,调整堆。所以要清楚这个堆有什么特点。

(3)堆:堆通常是一个可以被看做一棵完全二叉树的数组对象,因为堆可以看做是完全二叉树。则完全二叉树的特点:

  • a. 假设完全二叉树总节点数为n,则会有n/2个父节点

  • b. 对一棵有n个结点的完全二叉树的结点按层序编号, 则对任一结点i (1≤i≤n) ,若2i>n,则结点i无左孩子,否则左孩子的结点为2i;如果2i+1>n,则结点i无右孩子,否则右孩子结点为2i+1

  • c. 完全二叉树的叶子结点也只能出现最后两层上

对于上面完全二叉树中a,b中这个关系对我们进行堆排序进行构建堆,调整堆很关键。

(4)手动模拟构造堆:(为了方便理解,我这里下标i从1开始, n=8)

  • step1:对待排序数组按完全二叉树方式排列出来; 调整堆:自下往上逐步调整。先找到最后一个父节点n/2=4,判断i=4结点的孩子结点较大是否大于父节点,若大于则交换数据

  • step2-5:继续向上调整,调整过程和step1一样,但是在调整的过程中,可能会破坏下一级的大顶堆结构,所以还需要向下检查,例如图中step4中i=1中53和87交换后,破坏了i=3处大顶堆的结构,则需要调整。

  • 在大顶堆构造好后,将根结点与最后一个结点交换位置后又重新开始调整堆(如下图)
    在这里插入图片描述
    用代码跑出来的堆排序结果:

-------heapSortTest-------
I am a data array with 8 items.
(53, if)  (17, then)  (78, else)  (9, switch)  (45, case)  (65, for)  (87, while)  (32, break)  
The parent position is 3 and the child is 7
Move 32 to position 3
Adjust 3 to 8: I am a data array with 8 items.
(53, if)  (17, then)  (78, else)  (32, break)  (45, case)  (65, for)  (87, while)  (9, switch)  
The parent position is 2 and the child is 6
Move 87 to position 2
Adjust 2 to 8: I am a data array with 8 items.
(53, if)  (17, then)  (87, while)  (32, break)  (45, case)  (65, for)  (78, else)  (9, switch)  
The parent position is 1 and the child is 4
Move 45 to position 1
Adjust 1 to 8: I am a data array with 8 items.
(53, if)  (45, case)  (87, while)  (32, break)  (17, then)  (65, for)  (78, else)  (9, switch)  
The parent position is 0 and the child is 2
Move 87 to position 0
The parent position is 2 and the child is 6
Move 78 to position 2
Adjust 0 to 8: I am a data array with 8 items.
(87, while)  (45, case)  (78, else)  (32, break)  (17, then)  (65, for)  (53, if)  (9, switch)  
The initial heap: I am a data array with 8 items.
(87, while)  (45, case)  (78, else)  (32, break)  (17, then)  (65, for)  (53, if)  (9, switch)  

The parent position is 0 and the child is 2
Move 78 to position 0
The parent position is 2 and the child is 5
Move 65 to position 2
Adjust 0 to 7: I am a data array with 8 items.
(78, else)  (45, case)  (65, for)  (32, break)  (17, then)  (9, switch)  (53, if)  (87, while)  
Round 1: I am a data array with 8 items.
(78, else)  (45, case)  (65, for)  (32, break)  (17, then)  (9, switch)  (53, if)  (87, while)  
The parent position is 0 and the child is 2
Move 65 to position 0
The parent position is 2 and the child is 5
Adjust 0 to 6: I am a data array with 8 items.
(65, for)  (45, case)  (53, if)  (32, break)  (17, then)  (9, switch)  (78, else)  (87, while)  
Round 2: I am a data array with 8 items.
(65, for)  (45, case)  (53, if)  (32, break)  (17, then)  (9, switch)  (78, else)  (87, while)  
The parent position is 0 and the child is 2
Move 53 to position 0
Adjust 0 to 5: I am a data array with 8 items.
(53, if)  (45, case)  (9, switch)  (32, break)  (17, then)  (65, for)  (78, else)  (87, while)  
Round 3: I am a data array with 8 items.
(53, if)  (45, case)  (9, switch)  (32, break)  (17, then)  (65, for)  (78, else)  (87, while)  
The parent position is 0 and the child is 1
Move 45 to position 0
The parent position is 1 and the child is 3
Move 32 to position 1
Adjust 0 to 4: I am a data array with 8 items.
(45, case)  (32, break)  (9, switch)  (17, then)  (53, if)  (65, for)  (78, else)  (87, while)  
Round 4: I am a data array with 8 items.
(45, case)  (32, break)  (9, switch)  (17, then)  (53, if)  (65, for)  (78, else)  (87, while)  
The parent position is 0 and the child is 1
Move 32 to position 0
Adjust 0 to 3: I am a data array with 8 items.
(32, break)  (17, then)  (9, switch)  (45, case)  (53, if)  (65, for)  (78, else)  (87, while)  
Round 5: I am a data array with 8 items.
(32, break)  (17, then)  (9, switch)  (45, case)  (53, if)  (65, for)  (78, else)  (87, while)  
The parent position is 0 and the child is 1
Move 17 to position 0
Adjust 0 to 2: I am a data array with 8 items.
(17, then)  (9, switch)  (32, break)  (45, case)  (53, if)  (65, for)  (78, else)  (87, while)  
Round 6: I am a data array with 8 items.
(17, then)  (9, switch)  (32, break)  (45, case)  (53, if)  (65, for)  (78, else)  (87, while)  
Adjust 0 to 1: I am a data array with 8 items.
(9, switch)  (17, then)  (32, break)  (45, case)  (53, if)  (65, for)  (78, else)  (87, while)  
Round 7: I am a data array with 8 items.
(9, switch)  (17, then)  (32, break)  (45, case)  (53, if)  (65, for)  (78, else)  (87, while)  
Result
I am a data array with 8 items.
(9, switch)  (17, then)  (32, break)  (45, case)  (53, if)  (65, for)  (78, else)  (87, while)  

2.代码

堆排序我觉得一定要借助图像,不然很难仅用脑子去想象这个过程。

  • (1)结合文章的代码,需要注意的是这里下标i不是从1开始的,是从0开始的,则i其左孩子结点为2i+1,右孩子结点为2i

  • (2)先看**adjustHeap(int paraStart, int paraLength)**这个方法中,for循环是根据i处父节点向下去筛选最大的结点,第一个if是判断父节点的孩子结点中的最大结点 第二个if则是与父节点进行比较,是否大于父节点,若大于则需要交换位置,在这里,交换了父节点并不能确定父节点的最终位置,因为可能交换了位置会破坏下面的堆结构,还需要向下继续调整。

  • (3)堆排序方法heapSort(),第一个for循环是构建初始堆,第二个循环则是在循环输出堆排序,我们从代码也可以看到,每取一个堆顶元素则要进行一次堆调整

  /**
     * heap sort. Maybe the most difficult sorting algorithm.
     */
    public void heapSort() {
        DataNode tempNode;
        //step1 Construct the initial heap
        for (int i = length/2 -1 ; i >= 0; i--){
            adjustHeap(i, length);
        }
        System.out.println("The initial heap: " + this + "\r\n");

        //step2 swap and reconstruct
        for (int i = length -1; i > 0; i--) {
            tempNode = data[0];
            data[0] = data[i];
            data[i] = tempNode;

            adjustHeap(0, i);
            System.out.println("Round " + (length - i) + ": " + this);
        }



    }

    /**
     * Adjust the heap
     * @param paraStart the start of the index
     * @param paraLength the length of the adjusted sequence
     */
    public void adjustHeap(int paraStart, int paraLength) {
        DataNode tempNode = data[paraStart];
        int tempParent = paraStart;
        int tempKey = data[paraStart].key;

        for (int tempChild = paraStart*2 + 1; tempChild <  paraLength; tempChild = tempChild*2 + 1) {
            //the right child is bigger
            if (tempChild + 1 < paraLength) {
                if (data[tempChild].key < data[tempChild+1].key) {
                    tempChild++;
                }
            }

            System.out.println("The parent position is " + tempParent + " and the child is " + tempChild);
            if (tempKey < data[tempChild].key) {
                // the child is bigger
                data[tempParent] = data[tempChild];
                System.out.println("Move " + data[tempChild].key + " to position " + tempParent);
                tempParent = tempChild;
            } else {
                break;
            }
        }

        data[tempParent] = tempNode;
        System.out.println("Adjust " + paraStart + " to " + paraLength + ": " + this);
    }

    public static void heapSortTest() {
        int[] tempUnsortedKeys = { 5, 3, 6, 10, 7, 1, 9 };
        //int[] tempUnsortedKeys = { 53, 17, 78, 9, 45, 65, 87, 32};
        String[] tempContents = { "if", "then", "else", "switch", "case", "for", "while" };
       // String[] tempContents = { "if", "then", "else", "switch", "case", "for", "while" , "break"};
        DataArray tempDataArray = new DataArray(tempUnsortedKeys, tempContents);

        System.out.println(tempDataArray);

        tempDataArray.heapSort();
        System.out.println("Result\r\n" + tempDataArray);
    }

运行结果:

-------heapSortTest-------
I am a data array with 7 items.
(5, if)  (3, then)  (6, else)  (10, switch)  (7, case)  (1, for)  (9, while)  
The parent position is 2 and the child is 6
Move 9 to position 2
Adjust 2 to 7: I am a data array with 7 items.
(5, if)  (3, then)  (9, while)  (10, switch)  (7, case)  (1, for)  (6, else)  
The parent position is 1 and the child is 3
Move 10 to position 1
Adjust 1 to 7: I am a data array with 7 items.
(5, if)  (10, switch)  (9, while)  (3, then)  (7, case)  (1, for)  (6, else)  
The parent position is 0 and the child is 1
Move 10 to position 0
The parent position is 1 and the child is 4
Move 7 to position 1
Adjust 0 to 7: I am a data array with 7 items.
(10, switch)  (7, case)  (9, while)  (3, then)  (5, if)  (1, for)  (6, else)  
The initial heap: I am a data array with 7 items.
(10, switch)  (7, case)  (9, while)  (3, then)  (5, if)  (1, for)  (6, else)  

The parent position is 0 and the child is 2
Move 9 to position 0
The parent position is 2 and the child is 5
Adjust 0 to 6: I am a data array with 7 items.
(9, while)  (7, case)  (6, else)  (3, then)  (5, if)  (1, for)  (10, switch)  
Round 1: I am a data array with 7 items.
(9, while)  (7, case)  (6, else)  (3, then)  (5, if)  (1, for)  (10, switch)  
The parent position is 0 and the child is 1
Move 7 to position 0
The parent position is 1 and the child is 4
Move 5 to position 1
Adjust 0 to 5: I am a data array with 7 items.
(7, case)  (5, if)  (6, else)  (3, then)  (1, for)  (9, while)  (10, switch)  
Round 2: I am a data array with 7 items.
(7, case)  (5, if)  (6, else)  (3, then)  (1, for)  (9, while)  (10, switch)  
The parent position is 0 and the child is 2
Move 6 to position 0
Adjust 0 to 4: I am a data array with 7 items.
(6, else)  (5, if)  (1, for)  (3, then)  (7, case)  (9, while)  (10, switch)  
Round 3: I am a data array with 7 items.
(6, else)  (5, if)  (1, for)  (3, then)  (7, case)  (9, while)  (10, switch)  
The parent position is 0 and the child is 1
Move 5 to position 0
Adjust 0 to 3: I am a data array with 7 items.
(5, if)  (3, then)  (1, for)  (6, else)  (7, case)  (9, while)  (10, switch)  
Round 4: I am a data array with 7 items.
(5, if)  (3, then)  (1, for)  (6, else)  (7, case)  (9, while)  (10, switch)  
The parent position is 0 and the child is 1
Move 3 to position 0
Adjust 0 to 2: I am a data array with 7 items.
(3, then)  (1, for)  (5, if)  (6, else)  (7, case)  (9, while)  (10, switch)  
Round 5: I am a data array with 7 items.
(3, then)  (1, for)  (5, if)  (6, else)  (7, case)  (9, while)  (10, switch)  
Adjust 0 to 1: I am a data array with 7 items.
(1, for)  (3, then)  (5, if)  (6, else)  (7, case)  (9, while)  (10, switch)  
Round 6: I am a data array with 7 items.
(1, for)  (3, then)  (5, if)  (6, else)  (7, case)  (9, while)  (10, switch)  
Result
I am a data array with 7 items.
(1, for)  (3, then)  (5, if)  (6, else)  (7, case)  (9, while)  (10, switch)  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值