Sorting Algorithms swift :( iv) heapsort

Disclaimer: This article is a blogger original article, shall not be reproduced without the bloggers allowed. https://blog.csdn.net/lin1109221208/article/details/90694015

1 Overview

It refers to a heap sort algorithm to sort such a data structure designed for use heap.

A heap is approximately complete binary tree, and meet the bulk properties: child node key or index is always greater than / less than its parent node.

Top of the heap is divided into large and small heap pile top, big top of the heap is characterized by a complete binary tree root node is bigger than the left and right, top of the heap is characterized by small heap root value is less than the top left and right child nodes to be smaller.

1) large 顶堆

Assuming that the root node is numbered i, then the left child of the root node number is 2i, right child is numbered 2i + 1.

Relationship between the root and child nodes is: k (i)> = k (2i), k (i)> = k (2i + 1) i> = 1

2) small stack top

Assuming that the root node is numbered i, then the left child of the root node number is 2i, right child is numbered 2i + 1.

Relationship between the root and child nodes is: k (i) <= k (2i), k (i) <= k (2i + 1) i> = 1

 

2, algorithm principle

Idea: to build larger sequence disorderly heap top / top of a small heap, and finally sorted heap converted to uppercase traverse the level of the top of the heap sequence / small top of the heap, it is also desired

step:

1) The maximum adjustment stack Max_Heapify: The pile end child node adjusted, so that the child node is always less than the parent node, which is the object of maintaining the maximum heap nature, is a subroutine to create the core of the largest stack

2) create the maximum heap Build_Max_Heap: All data will heap reordered. The aim is to transform into an array maximum heap, and stack size to accept an array of two parameters, Build-Max-Heap will be a bottom-up calls Max-Heapify to transform the array, the establishment of maximum heap

3) HEAPSORT HeapSort: removing the root node of the first data bit, and make adjustments to the maximum stack recursive computation

 

3, for example

In [62, 88, 58, 47, 62, 35, 73, 51, 99, 37, 93] as an Example

1) a sequence from left to right into the above-described first complete binary tree

2) Construction of a large stack top

(1)先对子树进行调整,将其调整为大顶堆。找到完全二叉树最下方最小的以62为根节点的子树,先比较62的两个节点,93最大,由于62<93,所以交换62与93的位置。该子树的大顶堆构建完成

(2)以(1)的方式调整以47为根节点的子树,调整完成后,再分别调整以88和58为根节点的子树

(3)对整棵树进行调整,最终大顶堆构建完成

3)对大顶堆进行排序

(1)将大顶堆的第一个值(整个序列中最大的值)与大顶堆的最后一个值进行交换。

(2)交换后,最后一个值作为整个序列中最大值,将此值从大顶堆中剔除,再将剩下的元素再次进行调整为大顶堆。

4、算法实现

从小到大的排序思路:把一堆数字调整成大顶堆->堆顶元素和末尾元素交换->去掉末尾元素,继续大顶堆调整->重复以上动作

堆是通过数组实现的:

     1)父结点i的左子节点的位置---(2*i+1)

     2)父结点i的右子节点的位置---(2*i+2)

     3)子结点i的父结点的位置---floor((i-1)/2)  floor函数的作用是向下取整

    func heapSort(_ array : inout Array<Int>){
        //1、构建大顶堆
        
        //从二叉树的一边的最后一个结点开始
        for i in (0...(array.count/2-1)).reversed() {
            //从第一个非叶子结点从下至上,从右至左调整结构
            SortSummary.adjustHeap(&array, i, array.count)
        }
        //2、调整堆结构+交换堆顶元素与末尾元素
        for j in (1...(array.count-1)).reversed() {
            //将堆顶元素与末尾元素进行交换
            array.swapAt(0, j)
            //重新对堆进行调整
            SortSummary.adjustHeap(&array, 0, j)
        }
    }

    //调整大顶堆(仅是调整过程,建立在大顶堆以构建的基础上)
    func adjustHeap(_ array : inout Array<Int>, _ i : Int, _ length : Int){
        var i = i
        //取出当前元素i
        let tmp = array[i]
        var k = 2*i+1
        //从i结点的左子节点开始,也就是2i+1处开始
        while k < length {
            //如果左子节点小于右子节点,k指向右子节点
            if k+1<length && array[k]<array[k+1]{
                k += 1
            }
            //如果子节点大于父结点,将子节点值赋给父结点,不用进行交换
            if array[k]>tmp {
                array[i] = array[k]
                //记录当前结点
                i = k
            }else{
                break
            }
            //下一个结点
            k = k*2+1
        }
        //将tmp值放到最终的位置
        array[i] = tmp
    }

5、时间复杂度

1)在构建堆的过程中,由于是是完全二叉树从最下层最右边非终端节点开始构建,将它与子节点进行比较,对于每个非终端节点而言,最多进行两次比较和交换操作,因此构建堆的时间复杂度为O(n)

2)在整个排序过程中,第 i 次去堆顶记录重建堆需要时间为logi ,并且需要取 n - 1次堆记录,所以重建堆的时间复杂度为O(nlogn)。

3)堆的时间复杂度为O(nlogn)

 

github代码

注:排序的具体实现代码在 SortSummary.swift 文件里 调用是在 ViewController.swift

Guess you like

Origin blog.csdn.net/lin1109221208/article/details/90694015