排序
排序介绍
排序是将一组数据,依指定的顺序进行排列的过程。
排序的分类:
1)内部排序:
将所需要处理的所有数据都加载到内部存储器中进行排序。包括:交换式排序法、选择式排序法和插入式排序法
2)外部排序:
数据量过大时,无法全部加载到内存中,需要借助外部存储器进行排序。有:合并排序法 和 直接合并排序法
交换式排序法
运用数据比较后,以判断规则对数据位置进行交换,以达到排序的目的。
交换式排序法又可分为:
1)冒泡排序法(Bubble sort)
2)快速排序法(Quick sort)
冒泡排序:
1)通过对待排序序列从后向前(从下标较大的元素开始),一次比较相邻元素的排序码,若发现逆序则交换,是排序码较小的元素从后部向前部(从下标较大的单元移向下标较小的单元),就像水底的下的气泡一样逐渐向上冒。
2)排序的过程中,各元素不断接近自己的位置,如果一趟比较下来没有进行过交换,说明序列有序,因此要在排序过程中设置一个标识flag判断元素是否进行过交换。从而减少不必要的比较。(优化)
//冒泡法:分为轮次和每轮的交换次数,两者的关系为 第几轮+该轮交换次数 = 数组长度
//从后往前
func bubbleSort(slice []int) {
for i := 1; i < len(slice); i++ { //总轮数= 数组长度-1
temp := 0
flag := 0
for j := len(slice) - 1; j >= i; j-- { //表示第i论时的j次交换 i + j = 5
if slice[j] < slice[j-1] {
temp = slice[j]
slice[j] = slice[j-1]
slice[j-1] = temp
flag++
}
}
if flag == 0 {
switch i {
case 1:
fmt.Println("本身有序")
default:
fmt.Printf("第%v轮完成排序\n", i-1)
}
break
}
}
fmt.Println("排序后:", slice)
}
//从前往后
func bubbleSort1(slice []int) {
for i := 1; i < len(slice); i++ { //总轮数= 数组长度-1
temp := 0
flag := 0
for j := 0; j < len(slice)-i; j++ { //表示第i论时的j次交换 i + j = 5
if slice[j] > slice[j+1] {
temp = slice[j]
slice[j] = slice[j+1]
slice[j+1] = temp
flag++
}
}
if flag == 0 {
switch i {
case 1:
fmt.Println("本身有序")
default:
fmt.Printf("第%v轮完成排序\n", i-1)
}
break
}
}
fmt.Println("从前向后~排序后:", slice)
}
func main() {
intArr := [5]int{1, 15, 29, 8, 16}
slice := intArr[:]
fmt.Println("slice排序前:", slice) //slice排序前: [1 15 29 8 16]
bubbleSort(slice) //排序后: [1 8 15 16 29]
fmt.Println("-------------")
bubbleSort1(slice) //本身有序 从前向后~排序后: [1 8 15 16 29]
fmt.Println("intArr排序后:", intArr) //intArr排序后: [1 8 15 16 29]
}
Output
slice排序前: [1 15 29 8 16]
第2轮完成排序
排序后: [1 8 15 16 29]
本身有序
从前向后~排序后: [1 8 15 16 29]
intArr排序后: [1 8 15 16 29]
查找
在Golang中,常用的查找有两种:
1)顺序查找
2)二分查找(前提条件:该数组是有序的)
顺序查找
案例:
//顺序查找
var name string
fmt.Println("请输入查找的名字:")
fmt.Scanln(&name)
strArr := [5]string{"IronMan", "Spyder", "Doctor", "Hoke"}
index := -1
for i := 0; i < len(strArr); i++ {
if name == strArr[i] {
index = i
break
}
}
if index != -1 {
fmt.Printf("找到%v,下标为%d\n", strArr[index], index)
} else {
fmt.Println("没有找到,", name)
}
请输入查找的名字:
Spyder
找到Spyder,下标为1
二分查找
基本思路:
1.有序从小到大的数组arr,要查找的数是dstVal
2.先找到中间下标middle=(leftIndex+rightIndex)/2
对应的值,与dstVal进行比较,存在三种情况:
2.1 如果arr[middel]> dstVal
,就该在leftIndex---middle-1
下标范围内寻找是否有元素值等于desVal
2.2如果arr[middel]< dstVal
,就该在middle+1---rightIndex
下标范围内寻找是否有元素值等于desVal
2.3恰好arr[middle]==dstVal
,找到
3.退出递归的条件:由于leftIndex
在递归中往右移动,增大;reightIndex
在递归中往左移动,减小;故当rightIndex<leftIndex
成立时,退出递归。
package main
import (
"fmt"
)
func binaryFind(ptrArr *[5]int, leftIndex int, rightIndex int, dstVal int) {
if rightIndex < leftIndex {
fmt.Println("没找到")
return //跳出程序 沒有此处会无限报“没找到”
}
middle := (leftIndex + rightIndex) / 2
if (*ptrArr)[middle] > dstVal {
binaryFind(ptrArr, leftIndex, middle-1, dstVal)
} else if (*ptrArr)[middle] < dstVal {
binaryFind(ptrArr, middle+1, rightIndex, dstVal)
} else {
fmt.Printf("找到%v,下标为%v\n", dstVal, middle)
}
}
func main() {
/*
arr := [5]int{1, 5, 52, 152, 188}
binaryFind(&arr, 0, len(arr)-1, 188)
}