igozhang

——

    go_sort

    用go语言实现插入排序,希尔排序,冒泡排序,堆排序,选择排序,快速排序,归并排序算法并注释说明时间复杂度及原理
    
    插入排序:
    // 时间复杂度:O(n^2)
    // 原理:插入排序是一种简单的排序算法,它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
    func InsertionSort(arr []int) {
    	for i := 1; i < len(arr); i++ {
    		for j := i; j > 0; j-- {
    			if arr[j] < arr[j-1] {
    				arr[j], arr[j-1] = arr[j-1], arr[j]
    			}
    		}
    	}
    }
    希尔排序:
    // 时间复杂度:O(n^1.3)
    // 原理:希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
    func ShellSort(arr []int) {
    	n := len(arr)
    	h := 1
    	for h < n/3 {
    		h = 3*h + 1
    	}
    	for h >= 1 {
    		for i := h; i < n; i++ {
    			for j := i; j >= h && arr[j] < arr[j-h]; j -= h {
    				arr[j], arr[j-h] = arr[j-h], arr[j]
    			}
    		}
    		h /= 3
    	}
    }
    冒泡排序:
    // 时间复杂度:O(n^2)
    // 原理:冒泡排序是一种简单的排序算法,它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。
    func BubbleSort(arr []int) {
    	for i := 0; i < len(arr); i++ {
    		for j := 0; j < len(arr)-i-1; j++ {
    			if arr[j] > arr[j+1] {
    				arr[j], arr[j+1] = arr[j+1], arr[j]
    			}
    		}
    	}
    }
    堆排序:
    // 时间复杂度:O(nlogn)
    // 原理:堆排序是一种树形选择排序,是对直接选择排序的有效改进。堆的定义如下:具有n个元素的序列(h1,h2,...,hn),当且仅当满足(hi>=h2i,hi>=2i+1)或(hi<=h2i,hi<=2i+1)(i=1,2,...,n/2)时称之为堆。
    func HeapSort(arr []int) {
    	n := len(arr)
    	// 构建大顶堆
    	for i := n/2 - 1; i >= 0; i-- {
    		heapify(arr, i, n)
    	}
    	// 堆排序
    	for i := n - 1; i > 0; i-- {
    		arr[0], arr[i] = arr[i], arr[0]
    		heapify(arr, 0, i)
    	}
    }
    func heapify(arr []int, i, n int) {
    	for {
    		maxPos := i
    		if i*2+1 < n && arr[i] < arr[i*2+1] {
    			maxPos = i*2 + 1
    		}
    		if i*2+2 < n && arr[maxPos] < arr[i*2+2] {
    			maxPos = i*2 + 2
    		}
    		if maxPos == i {
    			break
    		}
    		arr[i], arr[maxPos] = arr[maxPos], arr[i]
    		i = maxPos
    	}
    }
    选择排序:
    // 时间复杂度:O(n^2)
    // 原理:选择排序是一种简单直观的排序算法,它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。
    func SelectionSort(arr []int) {
    	for i := 0; i < len(arr); i++ {
    		minIndex := i
    		for j := i + 1; j < len(arr); j++ {
    			if arr[j] < arr[minIndex] {
    				minIndex = j
    			}
    		}
    		arr[i], arr[minIndex] = arr[minIndex], arr[i]
    	}
    }
    快速排序:
    // 时间复杂度:O(nlogn)
    // 原理:快速排序是对冒泡排序的一种改进,它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
    func QuickSort(arr []int) {
    	quickSort(arr, 0, len(arr)-1)
    }
    func quickSort(arr []int, left, right int) {
    	if left < right {
    		pivot := partition(arr, left, right)
    		quickSort(arr, left, pivot-1)
    		quickSort(arr, pivot+1, right)
    	}
    }
    func partition(arr []int, left, right int) int {
    	pivot := arr[right]
    	i := left
    	for j := left; j < right; j++ {
    		if arr[j] < pivot {
    			arr[i], arr[j] = arr[j], arr[i]
    			i++
    		}
    	}
    	arr[i], arr[right] = arr[right], arr[i]
    	return i
    }
    归并排序:
    // 时间复杂度:O(nlogn)
    // 原理:归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。
    func MergeSort(arr []int) {
    	mergeSort(arr, 0, len(arr)-1)
    }
    func mergeSort(arr []int, left, right int) {
    	if left < right {
    		mid := (left + right) / 2
    		mergeSort(arr, left, mid)
    		mergeSort(arr, mid+1, right)
    		merge(arr, left, mid, right)
    	}
    }
    func merge(arr []int, left, mid, right int) {
    	tmp := make([]int, right-left+1)
    	i := left
    	j := mid + 1
    	k := 0
    	for i <= mid && j <= right {
    		if arr[i] <= arr[j] {
    			tmp[k] = arr[i]
    			i++
    			k++
    		} else {
    			tmp[k] = arr[j]
    			j++
    			k++
    		}
    	}
    	for i <= mid {
    		tmp[k] = arr[i]
    		i++
    		k++
    	}
    	for j <= right {
    		tmp[k] = arr[j]
    		j++
    		k++
    	}
    	copy(arr[left:right+1], tmp)
    }
    

    MP3