经典排序算法GO语言

基础算法

  • 冒泡排序
  • 快速排序
  • 选择排序
  • 插入排序

这里我们简单用GO实现常见的排序查找算法,例如冒泡,快排等。

冒泡排序

冒泡排序的原理是,这里以降序排序为例,对给定的数组进行多次遍历,每次均比较相邻的两个数,如果前一个比后一个大,则交换这两个数。经过第一次遍历之后,最大的数就在最右侧了;第二次遍历之后,第二大的数就在右数第二个位置了;以此类推,每一次循环比较最终都会有一个数排在它最终的位置上。

package main

import "fmt"

func main() {
	values := []int{4, 93, 84, 85, 80, 37, 81, 93, 27,12}
	bubbleSort(values)
	fmt.Println("升序排序:")
	fmt.Println(values)
	BubbleReSort(values)
	fmt.Println("逆序排序:")
	fmt.Println(values)
}

func bubbleSort(arrs []int){
	for i := 0; i < len(arrs)-1; i++ {  //外循环次数为 切片长度 - 1
		for j := i+1; j < len(arrs); j++ { // 每一次内循环,两两比较
			if  arrs[i]>arrs[j]{ // 如果前一个数 比 后一个 数大,就交换位置,使小数在左边,大数在右边
				arrs[i],arrs[j] = arrs[j],arrs[i]
			}
		}
	}
}

func BubbleReSort(values []int) {
	for i := 0; i < len(values)-1; i++ {//外循环次数为 切片长度 - 1
		for j := i+1; j < len(values); j++ {// 每一次内循环,两两比较
			if  values[i]

经典排序算法GO语言_第1张图片

快速排序

基本思想: 通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

快速排序算法通过多次比较和交换来实现排序,其排序流程如下:

  1. 首先设定一个分界值,通过该分界值将数组分成左右两部分。
  2. 将大于或等于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边。此时,左边部分中各元素都小于或等于分界值,而右边部分中各元素都大于或等于分界值。
  3. 然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理。
  4. 重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。当左、右两个部分各数据排序完成后,整个数组的排序也就完成了。
func quickSort(values []int, left, right int) {
   temp := values[left]  // temp 临时存放基数
   p := left   // p 就是 基数位置的索引 
   i, j := left, right

   for i <= j {
   	for j >= p && values[j] >= temp { //从右向左找第一个 小于 基数 的值
   		j--
   	}
   	if j >= p {
   		values[p] = values[j]  // 小于基数的数,赋值给 基数位置
   		p = j
   	}

   	for i <= p && values[i] <= temp {  //从左向右 找第一个 大于基数的值
   		i++
   	}
   	if i <= p {  
   		values[p] = values[i]  // 大于基数的值,赋值给基数位置
   		p = i
   	}
   }
   values[p] = temp  // 一趟遍历找到基数的最终位置,基数将整个数组一份为二,左右两数组一次递归
   if p-left > 1 {
   	quickSort(values, left, p-1)
   }
   if right-p > 1 {
   	quickSort(values, p+1, right)
   }
}

// 第2种写法
func Quick2Sort(values []int) {
   if len(values) <= 1 {
   	return
   }
   mid, i := values[0], 1 //把第一个数值作为 基数值
   head, tail := 0, len(values)-1
   for head < tail {
   	fmt.Println(values)
   	if values[i] > mid {  //  比基数值大,交换位置,让较大值放在 右侧
   		values[i], values[tail] = values[tail], values[i]
   		tail--
   	} else {// 比基数值小,交换位置,叫较小值放在左侧
   		values[i], values[head] = values[head], values[i]
   		head++
   		i++
   	}
   }
   values[head] = mid // 当 head == tail时,为基数找到它的最终位置,将切片分为左右两切片,递归进行
   Quick2Sort(values[:head])
   Quick2Sort(values[head+1:])
}

选择排序

选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理是:第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。选择排序是不稳定的排序方法。

升序排序

// 升序排序  写法1
func selectSort(nums []int) {
   length := len(nums)
   for i := 0; i < length; i++ {
   	maxIndex := 0 // 最大值的索引,开始假设,第一个数最大
   	//寻找最大的一个数,保存索引值
   	for j := 1; j < length-i; j++ { // 每一次遍历,都会有一个数值在它最终的位置上
   		if nums[j] > nums[maxIndex] {
   			maxIndex = j
   		}
   	}	
   	nums[length-i-1], nums[maxIndex] = nums[maxIndex], nums[length-i-1]
   	fmt.Println(nums) // 方便看到每一次排序后的结果
   }
}
// 升序排序 写法2
func selectSort2(nums []int) {
   length := len(nums)
   for i := 0; i < length-1; i++ {
   	min := i
   	//寻找最小的一个数,保存索引值
   	for j := i + 1; j < length; j++ {
   		if nums[min] > nums[j] {
   			min = j
   		}
   	}
   	nums[i], nums[min] = nums[min], nums[i]
   	fmt.Println(nums) // 方便看到每一次排序后的结果
   }
   }

降序排序

// 降序排序 写法1
func selectReSort(nums []int) {
	length := len(nums)
	for i := 0; i < length; i++ {
		maxIndex := i
		//寻找最大的一个数,保存索引值
		for j := i + 1; j < length; j++ { // 每一次遍历,都会有一个数值在它最终的位置上
			if nums[j] > nums[maxIndex] {
				maxIndex = j
			}
		}
		nums[i], nums[maxIndex] = nums[maxIndex], nums[i]
		fmt.Println(nums) // 方便看到每一次排序后的结果
	}
}
`

插入排序

将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。
从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。)

package main

import (
	"fmt"
)

func main() {
	values := []int{4, 93, 84, 85, 80, 37, 81, 93, 27,12}
	//start := time.Now().UnixNano()
	//insertSort(values)
	insertReSort(values)
	//end := time.Now().UnixNano()
	fmt.Println("最终排序:")
	//usetime := end - start
	fmt.Println(values)
	//fmt.Println("耗时:",usetime)
}
// 升序排序
func insertSort(arr []int){

	len := len(arr)
	for i := 1; i < len; i++ {  //从第二个开始,在有序队列中寻找合适位置插入
		temp := arr[i] // 记录要插入的值
		//fmt.Println("插入值:",temp)
		j := i  //从已经排序的序列最右边的开始比较,找到比其小的数
		for j > 0 && temp < arr[j - 1] {  // 在左侧有序队列从右向左一次比较,找到合适的位置
			arr[j] = arr[j - 1]
			j--
		}
		// 存在比其小的数,插入
		if j != i {
			arr[j] = temp
		}
		fmt.Println(arr)
	}
}

// 逆序排序
func insertReSort(arr []int){

	len := len(arr)
	for i := 1; i < len; i++ {  //从第二个开始,在有序队列中寻找合适位置插入
		temp := arr[i] // 记录要插入的值
		//fmt.Println("插入值:",temp)
		j := i  //从已经排序的序列最右边的开始比较,找到比其小的数
		for j > 0 && temp > arr[j - 1] {  // 在左侧有序队列从右向左一次比较,找到合适的位置
			arr[j] = arr[j - 1]
			j--
			//fmt.Println(arr)
		}
		// 找到合适位置,插入
		if j != i {
			arr[j] = temp
		}
		fmt.Println(arr)
	}
}

你可能感兴趣的:(go,算法,数据结构,排序算法,go)