Learning algorithms: sorting method used

Sorting is our daily development often encounter demand, for example, in the commodity list page, we can change the order of display items in accordance with various dimensions (sales price, popularity, etc.).

Therefore, knowledge of the performance of each sort of basis and also important. Let's sort this one to be an overall grasp.

  • Bubble Sort
  • Selection Sort
  • Insertion Sort
  • Shell sort
  • Heapsort
  • Merge sort
  • Quick Sort

For description of the sort of, this article does not use icons to specify, but at every step of the implementation of the code plus some log, are interested can copy the code to run their Playgroud view.

Bubble Sort

The basic idea

Any two adjacent recording, if the exchange reverse order, until there is no reverse order of record.

Code

func bubbleSort(_ items: [Int]) -> [Int] {
    var arr = items
    for i in 0..<arr.count {
        print("第\(i + 1)轮冒泡:")
        var j = arr.count - 1

        while j > i {
            if arr[j-1] > arr[j] {
                print("\(arr[j-1]) > \(arr[j]): 进行交换")
                arr.swapAt(j-1, j)
            } else {
                print("\(arr[j-1]) <= \(arr[j]): 不进行交换")
            }

            j -= 1
        }
        print("第\(i + 1)轮冒泡结束")
        print("当前结果为:\n\(arr)\n")
    }
    return arr
}
复制代码

According to the above implementation can be found if the array is similar to [2, 1, 3, 4, 5], then, after two bubbling, the array has been adjusted to [1, 2, 3, 4, 5]. At this point, then perform loop back is actually superfluous, so we found no bubble cycle exchange, it indicates the sort has been completed. Now we can look at the code optimization:

func bubbleSort_v2(_ items: [Int]) -> [Int] {
    var arr = items

    var flag = true

    for i in 0..<arr.count {
        print("第\(i + 1)轮冒泡:")

        if !flag {
            return []
        }

        flag = false

        var j = arr.count - 1

        while j > i {
            if arr[j-1] > arr[j] {
                print("\(arr[j-1]) > \(arr[j]): 进行交换")
                arr.swapAt(j-1, j)

                flag = true
            } else {
                print("\(arr[j-1]) <= \(arr[j]): 不进行交换")
            }

            j -= 1
        }
        print("第\(i + 1)轮冒泡结束")
        print("当前结果为:\n\(arr)\n")
    }
    return arr
}
复制代码

Selection Sort

The basic idea

Every time selecting a minimum (or maximum) of an element from data element to be sorted has been lined on the end of the sequence, until all the elements so far drained.

Code

func selectSort(_ items: [Int]) -> [Int] {
    var arr = items
    
    for i in 0..<arr.count {
        print("第\(i+1)轮选择,x选择下标的范围为\(i)----\(arr.count)")
        var j = i + 1
        var minValue = arr[i]
        var minIndex = i
        
        // 寻找无序部分中最小值
        while j < arr.count {
            if minValue > arr[j] {
                minValue = arr[j]
                minIndex = j
            }
            j = j + 1
        }
        
        print("在后半部分乱序数列中,最小值为:\(minValue),下标为:\(minIndex)")
        // 与无序表中的第一个值交换,让其成为有序表中的最后一个值
        if minIndex != i {
            arr.swapAt(minIndex, i)
        }
        print("本轮结果为:\(arr)\n")
    }
    
    return arr
}
复制代码

Insertion Sort

The basic idea

Each step will be a sort of record, the previously inserted row sorted in an ordered sequence to, until all elements have been exhausted plug can eventually get a sorted list.

Code

func insertSort(_ items: [Int]) -> [Int] {
    var arr = items
    
    for i in 0..<arr.count {
        print("第\(i)轮插入:")
        print("要选择插入的值为:\(arr[i])")
        var j = i
        
        while j > 0 {
            if arr[j] < arr[j-1] {
                arr.swapAt(j, j-1)
                
                j -= 1
            } else {
                break
            }
        }
        print("插入的位置:\(j)")
        print("本轮插入完毕,插入结果为:\n\(arr)\n")
    }
    
    return arr
}
复制代码

Shell sort

The basic idea

In fact, Hill sorting is an upgraded version of insertion sort, shell sort, also known as narrow incremental sorted according to the characteristics of its sort. Hill sorting step is first substantially random sequence according to certain steps (increments) are divided into groups, each of these data sets to be sorted by insertion sort of way. Then narrow step (increment) packet, then the data in the group are sorted again. Until increments of 1 position. After these steps, we ordered the sequence is. In fact, the above is the insertion sort, shell sort, in increments of 1.

Code

func hillSort(_ items: [Int]) -> [Int] {
    var arr = items
    
    var step: Int = arr.count / 2
    
    while step > 0 {
        print("步长为\(step)的插入排序开始:")
        for i in 0..<arr.count {
            var j = i + step
            
            while j >= step && j < arr.count {
                if arr[j] < arr[j-step] {
                    arr.swapAt(j, j-step)
                    
                    j = j - step
                } else {
                    break
                }
            }
        }
        print("步长为\(step)的插入排序结束")
        print("本轮排序结果为:\(arr)\n")
        step = step / 2      // 缩小步长
    }
    
    return arr
}
复制代码

Heapsort

Ready knowledge

Heap is a complete binary tree with the following properties: the value of each node is equal to or greater than the left and right child node values, called the large top stack; each node or a value less than or equal to its left child node value, known as the small stack top.

We nodes are numbered layers of the stack, which maps the logical structure into an array will look like.

大顶堆: arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2]

小顶堆: arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2]

The basic idea

Collating sequence to be configured into a large pile top, at this time, the maximum value of the root node is the top of the stack of the entire sequence. To be exchanged with the last element on the end of this time the maximum value. The remaining n-1 th element of a stack is reconfigured, it would receive the next smallest value of n elements. So again executed, it will be able to get an ordered sequence of.

The basic steps

  1. The random sequence to construct a stack, heap, or choose a large top ascending descending minor vertex according to the needs of the stack.
  2. The top of the stack elements and switching elements at the end, the largest element will "sink" to the end of the array.
  3. Readjust the structure, so as to satisfy the definition of the stack, and then continue to exchange end of the current top of the stack elements and elements, and adjust the exchange step is repeatedly executed until the entire sequence of ordered.

Code

// 构建小顶堆的层次遍历序列
func heapCreate(items: inout Array<Int>) {
    var i = items.count
    while i > 0 {
        heapAdjast(items: &items, startIndex: i - 1, endIndex: items.count)
        
        i -= 1
    }
}

// 对小顶堆j的局部进行调整, 使其该节点的所有父类符合小顶堆的特点
func heapAdjast(items: inout Array<Int>, startIndex: Int, endIndex: Int) {
    let temp = items[startIndex]
    var fatherIndex = startIndex + 1    //父节点下标
    var maxChildIndex = 2 * fatherIndex //左孩子下标
    
    while maxChildIndex <= endIndex {
        if maxChildIndex < endIndex && items[maxChildIndex-1] < items[maxChildIndex] {
            maxChildIndex = maxChildIndex + 1
        }
        
        if temp < items[maxChildIndex-1] {
            items[fatherIndex-1] = items[maxChildIndex-1]
        } else {
            break
        }
        fatherIndex = maxChildIndex
        maxChildIndex = 2 * fatherIndex
    }
    items[fatherIndex-1] = temp
}

func heapSort(_ items: [Int]) -> [Int] {
    var arr = items
    
    var endIndex = arr.count - 1
    
    print("原始堆")
    print(arr)
    
    // 创建小顶堆,其实就是讲arr转换成小顶堆层次的遍历结果
    heapCreate(items: &arr)
    
    print(arr)
    
    print("堆排序开始")
    while endIndex > 0 {
        // 将小顶堆的定点与小顶堆的最后一个值进行交换
        arr.swapAt(endIndex, 0)
        
        endIndex -= 1    // 缩小小顶堆的范围
        
        // 对交换后的小顶堆进行调整,使其重新成为小顶堆
        print("重新调整")
        heapAdjast(items: &arr, startIndex: 0, endIndex: endIndex + 1)
        print("调整后的结果如下")
        print(arr)
    }
    
    return arr
}
复制代码

Merge sort

The basic idea

Merge sort is a sorting method using the merge of ideas implemented, the algorithm uses the classic divide and conquer strategy.

Will be sorted array into a separate sub-elements, which pairwise comparison will be combined into an ordered array, and the combined repeated comparison process, until the number of elements in the array and the original ordered array of the same after merger , the sort end.

Code

// 合并两个数组
func mergeArray(firstList: Array<Int>, secondList: Array<Int>) -> Array<Int> {
    var resultList: Array<Int> = []
    var firstIndex = 0
    var secondIndex = 0
    
    // 拿出两数组第一个元素,比较之后取小的插入新数组
    while firstIndex < firstList.count && secondIndex < secondList.count {
        if firstList[firstIndex] < secondList[secondIndex] {
            resultList.append(firstList[firstIndex])
            firstIndex += 1
        } else {
            resultList.append(secondList[secondIndex])
            secondIndex += 1
        }
    }
    
    // 将第一个数组剩下的元素插入新数组
    while firstIndex < firstList.count {
        resultList.append(firstList[firstIndex])
        firstIndex += 1
    }
    
    // 将第二个数组剩下的元素插入新数组
    while secondIndex < secondList.count {
        resultList.append(secondList[secondIndex])
        secondIndex += 1
    }
    
    return resultList
}

func mergeSort(_ items: [Int]) -> [Int] {
    let arr = items
    
    // 将数组中的每一个元素放入一个数组中
    var tempArray: Array<Array<Int>> = []
    for item in arr {
        var subArray: Array<Int> = []
        subArray.append(item)
        tempArray.append(subArray)
    }
    
    // 对这个数组中的数组进行合并,直到合并完毕为止
    while tempArray.count != 1 {
        print(tempArray)
        var i = 0
        while i < tempArray.count - 1 {
            print("将\(tempArray[i])与\(tempArray[i+1])合并")
            tempArray[i] = mergeArray(firstList: tempArray[i], secondList: tempArray[i+1])
            print("合并结果为:\(tempArray[i])\n")
            tempArray.remove(at: i + 1)
            i = i + 1
        }
    }
    
    return tempArray.first!
}
复制代码

Quick Sort

The basic idea

Quick Sort (Quick Sort) using a divide and conquer strategy.

Selecting a reference number, to be sorted by the sorting trip data is divided into two separate portions; wherein a portion of all of the data than the other portion of all data to be smaller. Then, the data of the two parts in this way were quick sort, to sort the entire process can be recursively, in order to achieve the whole data into an ordered sequence.

Fast sorting process:

  1. Picked from a reference value the number of columns.
  2. All smaller than the reference value is placed in front of the reference, all larger than the reference values ​​of the reference swing back (the same number can either side); exit after partition, is in an intermediate position of the reference sequence.
  3. Recursively "in front of the reference value of the sub-columns" and "after the reference value of the sub series" sort.

Code

/// 将数组以第一个值为准分为两部分,前半部分比该值要小,后半部分比该值要大
///
/// - parameter list: 要二分的数组
/// - parameter low:  数组的下界
/// - parameter high: 数组的上界
///
/// - return: 分界点
func partition(list: inout Array<Int>, low: Int, high: Int) -> Int {
    var low = low
    var high = high
    let temp = list[low]
    
    while low < high {
        while low < high && list[high] >= temp {
            high -= 1
        }
        list[low] = list[high]
        
        while low < high && list[low] <= temp {
            low += 1
        }
        list[high] = list[low]
        
        print("====low==\(low)======high==\(high)")
    }
    
    list[low] = temp
    print("=====temp==\(temp)")
    print(list)
    return low
}

/// 快速排序
///
/// - parameter list: 要排序的数组
/// - parameter low:  数组的下界
/// - parameter high: 数组的上界
func quickSortHelper(list: inout Array<Int>, low: Int, high: Int) {
    if low < high {
        let mid = partition(list: &list, low: low, high: high)
        
        quickSortHelper(list: &list, low: low, high: mid - 1)
        quickSortHelper(list: &list, low: mid + 1, high: high)
    }
}

func quickSort(_ items: Array<Int>) -> Array<Int> {
    var list = items
    quickSortHelper(list: &list, low: 0, high: list.count - 1)
    print("快速排序结束")
    return list
}
复制代码

Swift sorting usage

Swift in the source code, sort function uses an algorithm IA (IntroSort). It is a heap sort, insertion sort, quicksort constitute three algorithms, the algorithm selects the best respective inputs is accomplished according to the depth.

// 以升序排列为例,array 数组可改变
array.sort

// 以降序排列为例,array 数组不可改变
newArray = array.sorted(by: >)
复制代码

to sum up

Sort method time complexity Auxiliary space
Bubble Sort O (n²) O (1)
Selection Sort O (n²) O (1)
Insertion Sort O (n²) O (1)
Shell sort Related to incremental selection strategy O (1)
Heapsort O (nlogn) O (1)
Merge sort O (nlogn) O (n)
Quick Sort O (nlogn) (Logn) -You (n)

Reproduced in: https: //juejin.im/post/5cf4955df265da1b7401e6da

Guess you like

Origin blog.csdn.net/weixin_33860528/article/details/91478235
Recommended