Go核心开发学习笔记(十九) —— 冒泡排序,顺序查找,二分查找

冒泡排序

  1. 重点,众多面试都考察冒泡排序
  2. 冒泡排序的基本思想:通过对 待排序序列从后向前(从下标大的元素开始),一次比较相邻的元素的排序码,若发现逆序则交换,使排序码较小的元素逐渐从后部移向。
  3. 因为排序过程中,各元素不断接近自己位置,如果一趟下来没有进行交换,说明序列有序,因此优化时 要在排序过程中设置一个标志flag判断元素是否进行交换,从而减少不必要的比较。

冒泡排序详细分解剖析

  1. 首先要存在一个数组或者切片

    • 已定义的数组:

       //方式1
       var array [n]int = [n]int{xx,xx,xx,...}
       //方式2
       var array = [...]int{xx,xx,xx,...}
       //方式3
       var array = make([]int,n)
      
    • 外部传入数字形成数组

      var n int = 0           //统计元素个数
      fmt.Println("请输入数组的元素个数: ")
      fmt.Scanf("%d", &n)
      var arr []int = make([]int, n)      //定义一个空切片,len为n
      for i := 0; i < n; i++ {
      	var n1 int
      	fmt.Printf("请输入第%d个元素的值:", i+1)
      	fmt.Scanf("%d", &n1)            //每个值都是切片中的一个值
      	arr[i] = n1                     //赋值完毕
      }
      
  2. 为了代码复用,写一个可以被调用的函数,命名为 bubbleSort(arr *[]int),要注意的是本函数传参一定要使用引用传递,通过本函数修改main()中的arr变量,所以需要传递指针类型变量

    func bubbleSort(arr *[]int) {
    	temp := 0                                 //定义一个中间变量当做交换值传递媒介
    	for i := 0; i < len(*arr)-1; i++ {        //外循环为确定最值的循环次数,所以为(数组元素-1)次
    		for j := 0; j < len(*arr)-1-i; j++ {  //内循环次数为元素两两交换次数,由于每外循环一次,最元素就不用再次比较,所以可以减少一次比较,随着外循环次数上升而减少
    			if (*arr)[j] < (*arr)[j+1] {      //元素j < 元素j+1 就交换,最后就是降序排列;
    				temp = (*arr)[j]              //元素j > 元素j+1就交换,那么就是升序排列。
    				(*arr)[j] = (*arr)[j+1]
    				(*arr)[j+1] = temp
    			}
    		}
    	}
    }
    

最终代码如下:

 package main
 import "fmt"
 
 func bubbleSort(arr *[]int) {
 	temp := 0
 	for i := 0; i < len(*arr)-1; i++ {
 		for j := 0; j < len(*arr)-1-i; j++ {
 			if (*arr)[j] > (*arr)[j+1] {
 				temp = (*arr)[j]
 				(*arr)[j] = (*arr)[j+1]
 				(*arr)[j+1] = temp
 			}
 		}
 	}
 }
 
 func main() {
 	/*
 		构建一个切片
 	*/
 	var n int
 	fmt.Println("请输入切片的元素个数: ")
 	fmt.Scanf("%d", &n)
 	var arr []int = make([]int, n)
 	for i := 0; i < n; i++ {
 		var n1 int
 		fmt.Printf("请输入第%d个元素的值:", i+1)
 		fmt.Scanf("%d", &n1)
 		arr[i] = n1
 	}
 	fmt.Println(arr)
 	/*
 		开始冒泡排序算法,从小到大排列(升序),从大到小排列(降序)
 	*/
 	bubbleSort(&arr)
 	fmt.Println(arr)
 }

顺序查找

顺序查找举例:

第一种方式:太啰嗦

package main
import "fmt"
func main() {
	var arr = [...]string{"主宰","美杜莎","幻影刺客","杨叫兽"}
	var heroName string
	fmt.Println("请输入你要查找的对象: ")
	fmt.Scanf("%v",&heroName)

	for i := 0 ; i < len(arr) ; i++ {
		if heroName == arr[i] {
			fmt.Printf("找到%v,下标为%v",heroName,i)
			break
		} else if i == len(arr) - 1 {
			fmt.Printf("没有找到%v",heroName)
		}
	}
}

第二种方式:下标改变即证明找到(推荐)

package main

import "fmt"

func main() {
	var arr = [...]string{"主宰","美杜莎","幻影刺客","杨叫兽"}
	var heroName string
	fmt.Println("请输入你要查找的对象: ")
	fmt.Scanf("%v",&heroName)
	index := -1

	for i := 0 ; i < len(arr) ; i++ {
		if heroName == arr[i] {

			index = i
			break
		}
	}
	if index != -1 {
		fmt.Printf("找到%v,下标为%v",heroName,index)
	} else {
		fmt.Printf("没有找到%v",heroName)
	}
}

二分查找

  • 重点,众多面试都考察二分查找

  • 二分查找的基本思想:首先数组一定要有序,这是进行二分查找的必要条件。

  • 二分查找的原理:求有序数列 两个最值leftindex&rightindex之和/2 得到一个middle的下标,通过middle下标的值和查找值比较,得到下面两种结果扩展:

    • 数组从小到大排列
      arr[middle] > findVal :递归查找结果范围变成 leftindex ~ middle - 1
      arr[middle] < findVal: 递归查找结果范围变成 middle + 1 ~ rightindex
      arr[middle] = findVal: 正好,一次性就找到了
      leftindex == rightindex : 最后一次比较
      leftindex > rightindex :找不到

    • 数组从大到小排列
      arr[middle] > findVal :递归查找结果范围变成 middle + 1 ~ rightindex
      arr[middle] < findVal: 递归查找结果范围变成 leftindex ~ middle - 1
      arr[middle] = findVal: 正好,一次性就找到了
      leftindex == rightindex : 最后一次比较
      leftindex > rightindex :找不到

    • 上述两种比较方式也就诠释了为何二分查找比顺序查找快很多,因为不断二分二分迅速完成查找。

最终代码如下:

package main

import "fmt"

func binaryFind(slice *[]int,leftin int,rightin int,findVal int) {
	midin := (leftin + rightin) / 2
	if leftin > rightin {
		fmt.Println("查找的内容不存在")
		return
	}
	if (*slice)[midin] > findVal {
		binaryFind(slice,leftin,midin - 1,findVal)
	}
	if (*slice)[midin] < findVal {
		binaryFind(slice,midin + 1,rightin,findVal)
	}
	if (*slice)[midin] == findVal {
		fmt.Println("找到了,下标为",midin)
	}
}

func main() {
	/*
	 - **重点,众多面试都考察二分查找**
	 - 二分查找的基本思想:首先数组一定要有序,这是进行二分查找的必要条件。
	 - 二分查找的原理:求有序数列 两个最值leftindex&rightindex之和/2 得到一个middle的下标,通过middle下标的值和查找值比较,得到下面两种结果扩展:

	     - **数组从小到大排列**
			arr[middle] > findVal :递归查找结果范围变成 leftindex ~ middle - 1
			arr[middle] < findVal: 递归查找结果范围变成 middle + 1 ~ rightindex
			arr[middle] = findVal: 正好,一次性就找到了
			leftindex == rightindex : 最后一次比较
			leftindex > rightindex :找不到

	     - **数组从大到小排列**
			arr[middle] > findVal :递归查找结果范围变成 middle + 1 ~ rightindex
			arr[middle] < findVal: 递归查找结果范围变成 leftindex ~ middle - 1
			arr[middle] = findVal: 正好,一次性就找到了
			leftindex == rightindex : 最后一次比较
			leftindex > rightindex :找不到
	   - 上述两种比较方式也就诠释了为何二分查找比顺序查找快很多,因为不断二分二分迅速完成查找。
	 */

	var arr = [...]int{2,3,4,6,8}
	slice := arr[:]
	binaryFind(&slice,0,4,2)
}
发布了49 篇原创文章 · 获赞 18 · 访问量 4010

猜你喜欢

转载自blog.csdn.net/weixin_41047549/article/details/89856943