zoukankan      html  css  js  c++  java
  • 排序算法的GO语言实现

    排序

    冒泡排序

    func BubbleSort(arr []int,arrLength int){
    	for i:=0; i<arrLength; i++{
    		flag := false
    		//每一轮操作完,有i个元素已经是有序的,同时最后一个元素没有比较对象,不用比
    		for j:=0;j<arrLength-i-1;j++{
    			if arr[j] > arr[j+1]{
    				arr[j],arr[j+1] = arr[j+1],arr[j]
    				flag = true
    			}
    		}
    		if !flag{
    			break
    		}
    	}
    }
    

    插入排序

    把数字插入到合适的位置

    package algo
    
    import "testing"
    
    /**
    第一个数字是有序的,从后面的数字取一个出来,放在有序范围内
     */
    func insertionSort(arr []int,arrLength int){
    	if arrLength <= 1 {
    		return
    	}
    	for i:=1; i<arrLength; i++ {
    		//从没有排序的区域取第一个
    		value := arr[i]
    		//从后往前,跟有序区域每一个数字比较
    		j := i-1 //i-1是有序区域最后一个数字
    		for ;j>=0;j--{
    			//如果值比某个数字小,则该数字需要往后挪动一个位置
    			if(arr[j] > value){
    				arr[j+1] = arr[j]
    			}else{
    				//有序区域已经没有比该数字更大,退出
    				break
    			}
    		}
    		//把数字放在挪动出来的空位,j+1是为了补偿j--
    		arr[j+1] = value
    	}
    }
    
    

    选择排序

    每次选择后面最小的数字放到有序区

    //在无序区选择一个最小的数字放在有序区后面
    func selectSort(arr []int,arrLength int){
    	for i:=0; i<arrLength; i++{
    		minIndex := i //先记录当前元素作为最小元素的索引
    		//在无序区(i+1),从前往后找最小的索引
    		for j:=i+1;j<arrLength;j++{
    			if arr[j] < arr[minIndex] {
    				minIndex = j
    			}
    		}
    		//用最小元素替换有序区末尾元素,此时该区域(0~i)才是真正有序
    		arr[minIndex],arr[i] = arr[i],arr[minIndex]
    	}
    }
    

    快排

    选择一个数字作为基准值,小的放左边,基准值放中间,大的放右边。不断重复这个过程

    /**
    选择一个数字作为基准值,小的放左边,大的放右边
     */
    func QuickSort(arr []int){
    	QuickSortInner(arr,0,len(arr)-1)
    }
    
    func QuickSortInner(arr []int,left int,right int){
    	//递归结束条件,左右两边的索引重合,表示已经所有条件
    	if(left >= right){
    		return
    	}
    	q := partition(arr,left,right) //分区,并返回两个区中间数的索引
    	partition(arr,left,q-1) //对小数区[left,q-1]分区
    	partition(arr,right,q+1)//对大数区分区
    }
    
    func partition(arr []int,left int,right int) int{
    	//选取最后一个值作为基准值
    	pivot := arr[right]
    	//有序区开始
    	j := left
    	//从左到右遍历,如果某个数字比基数小,该数字加入(交换) 已小数字区间[left,j-1]尾部,区间扩充
    	//否则加入大数字区间,区间位置不变
    	//(小->大)
    	for i:=left;i<right;i++{
    		if arr[i] < pivot {
    			arr[i],arr[j] = arr[j],arr[i]
    			j++
    		}
    	}
    	//基数需要跟大数字区间第一个数字交换(因为比他大的都放在第一个数字后了)
    	arr[j],arr[right] = arr[right],arr[j]
    	return j
    }
    

    归并排序

    把数组不断拆分成两半,直到成为一个单独的元素,然后传入数组的起点,中间点,终点,以中间点为边界合并两个有序的数组

    func mergerSort(arr []int,start int,end int){
    	//start >= end 表示整个数组已经拆分成一个个元素
    	if start >= end {
    		return
    	}
    	//把数组分成两半,分别对两半进行拆分
    	middle := start + (end - start) / 2
    	mergerSort(arr,start,middle)
    	mergerSort(arr,middle+1,end)
    	//拆分完后对两半进行合并操作
    	merge(arr,start,middle,end)
    }
    
    //对两个有序数组进行合并操作,i是起点到中间点,j是中间点+1到终点
    func merge(arr []int,start int, middle int, end int){
    	//分别设置三个变量,两个作为有序数组的偏移量,k作为新数组的偏移量
    	i := start
    	j := middle+1
    	k := 0
    	//申请一个两个数组合并后大小的空间
    	tmpArr := make([]int,end-start+1)
    	//循环结束的条件是 其中一个数组已经遍历完
    	//遍历的过程中新数组递加
    	for ;i<=middle && j<=end; k++ {
    		//把值更大的元素放入新数组,并且用该数组下一个元素对比
    		if arr[j] > arr[i]{
    			tmpArr[k] = arr[j]
    			j++
    		}else{
    			tmpArr[k] = arr[i]
    			i++
    		}
    	}
    
    	//把i数组未循环完的元素放入临时变量
    	for ;i<=middle;i++{
    		tmpArr[k] = arr[i]
    		k++
    	}
    
    	//把j数组未循环完的元素放入临时变量
    	for ;j<=end;j++{
    		tmpArr[k] = arr[j]
    		k++
    	}
    
    	//把新数组的元素放回原数组,原数组需要从起点start偏移
    	for i=0; i< len(tmpArr); i++{
    		arr[start+i] = tmpArr[i]
    	}
    }
    
    

    二分法

    等值查找

    场景:有序数据
    注意点:

    • 循环退出条件是 low <= high
    • low和high的更新,low=mid+1,high=mid-1。注意这里的 +1 和 -1,如果直接写成 low=mid 或者 high=mid,就可能会发生死循环。
    func bsearch(arr []int,value int) int{
    	length := len(arr)
    	high := length - 1
    	low := 0
    	for high >= low {
    		mid := low + (high - low)/2
    		if value == arr[mid] {
    			return mid
    		}else if(value > arr[mid]){
    			low = mid + 1
    		}else{
    			high = mid - 1
    		}
    	}
    	return -1
    }
    

    查找第一个大于等于value的元素

    • 如果 a[mid]小于要查找的值 value,那要查找的值肯定在[mid+1, high]之间,所以,我们更新 low=mid+1。
    • 对于 a[mid]大于等于给定值 value 的情况,我们要先看下这个 a[mid]是不是我们要找的第一个值大于等于给定值的元素。如果 a[mid]前面已经没有元素,或者前面一个元素小于要查找的值 value,那 a[mid]就是我们要找的元素。
    • 如果 a[mid-1]也大于等于要查找的值 value,那说明要查找的元素在[low, mid-1]之间,所以,我们将 high 更新为 mid-1。
    func bsearch(arr []int,value int) int{
    	length := len(arr)
    	high := length - 1
    	low := 0
    	for low <= high {
    		mid := low + (high - low)/2
                     //找到了一个大于等于value的元素
    		if  arr[mid] >= value {
    			//看看它前面有没有元素
                            //看看前一个元素是不是小于value
                            //都符合表示找到了
    			if mid == 0 || arr[mid - 1] < value {
    				return mid
    			}else{
    				//否则从mid前面找比value大的元素
    				high = mid - 1
    			}
    		}else{
    			//从后面找
    			low = mid + 1
    		}
    	}
    	return -1
    }
    
  • 相关阅读:
    [RxJS] Combination operators: concat, startWith
    [RxJS] Filtering operators: skipWhile and skipUntil
    [RxJS] Filtering operators: takeUntil, takeWhile
    [RxJS] Filtering operators: takeLast, last
    强连通tarjan模版
    HDU 4576 Robot (概率DP)
    Inside GDALAllRegister之二: 自动加载驱动
    [置顶] Java中字符串为什么不以结尾
    rcp(插件开发) The 'Eclipse-LazyStart' header is deprecated, use 'Bundle-ActivationPolicy'
    如何在模板中引用参数类中的一个特定member
  • 原文地址:https://www.cnblogs.com/jaychan/p/12701725.html
Copyright © 2011-2022 走看看