算法:选择排序

选择排序算法的实现思路有点类似插入排序,也分为已排序区间和未排序区间。但是选择排序每次会从未排序区间中找到最小的元素,将其放到已排序区间的末尾。

在这里插入图片描述

C++实现

#include <iostream>
#include <list>
#include <vector>
#include <map>


template<typename T>
std::ostream& print(std::ostream &out,T const &val) {
    return (out << val << " ");
}

template<typename T1,typename T2>
std::ostream& print(std::ostream &out,std::pair<T1,T2> const &val) {
    return (out << "{" << val.first << " " << val.second << "} ");
}

template<template<typename,typename...> class TT,typename... Args>
std::ostream& operator<<(std::ostream &out,TT<Args...> const &cont) {
    for(auto&& elem : cont) print(out,elem);
    out << "\n";
    return out;
}


void swap(int & i, int &j){
    int t = i;
    i = j;
    j = t;
}



void selectSort(std::vector<int> &vec){
    if(vec.empty() || vec.size() == 1){
        return;
    }

    int min ;
    for(int pos = 0; pos < vec.size(); pos++){
        min = pos;
        for(int i = pos + 1; i  < vec.size(); i++){
            if(vec[min] > vec[i]){
                min = i;
            }
        }

        if(min != pos){
            swap(vec[min], vec[pos]);
        }
    }


}
int main() {
    std::vector<int> vec = {1,9,2,8,3,7,4,6,5,10, -1};
    selectSort(vec);
    std::cout << vec;
    return 0;
}



java实现

版本1

从小到大:
1、定义一个10个int元素的数组。
2、选择第一个元素,将这个元素和剩下的九个元素相比,找出最小的那个,然后和第一个元素交换位置。如果第一个元素就是最小的元素,那么不需要交换位置(<或者>,而不是<=或者>=)
3、选择第二个元素,将这个元素和剩下的八个元素相比,找出最小的那个,然后和第二个元素交换位置。如果第二个元素就是最小的元素,那么不需要交换位置(<或者>,而不是<=或者>=)
4、。。。。。。

也可以这样想:假设第一个元素就是最小的那个元素,将这个元素和剩下的九个元素相比,看还有没有比它小的元素,如果有,就将这个元素放到最小元素的位置—第一个元素。。。。

package com.oceanstar.sort;

import java.util.Arrays;

public class sort {
    public static void main(String []args){
        int []arr = {199, 11, 23, 56, 55, 49, 88};
        selectSort(arr);
        System.out.println(Arrays.toString(arr));
    }


    public static int [] selectSort(int []arr){
        for(int i=0; i<arr.length-1; i++){
            for (int j=i+1; j<arr.length; j++){
                if (arr[i]>arr[j]){
                    int temp = arr[i];
                    arr[i] = arr[j];
                    arr[j] = temp;
                }
            }
        }
        return arr;
    }
    

}

总结:有序区逐步扩大,无序区逐步缩小
选择排序法需要比较:9+7++6+5+4+3+2+1次

版本2

从小到大:
1、定义一个10个int元素的数组。
2、选择第一个元素为最小的元素,并用一个index和num记录下此时的值与索引。然后分别拿这个值与剩下的值相比,如果有比这个元素还要小的元素,就用index和num记录下此时的值和索引。比较完一轮之后,如果发现index不为1,那么和第一个元素相交换。
3、选择第二个元素为最小的元素,并用一个index和num记录下此时的值与索引。然后分别拿这个值与剩下的值相比,如果有比这个元素还要小的元素,就用index和num记录下此时的值和索引。比较完一轮之后,如果发现index不为2,那么和第二个元素相交换。
4、。。。

package com.oceanstar.sort;

import java.util.Arrays;

public class sort {
    public static void main(String []args){
        int []arr = {199, 11, 23, 56, 55, 49, 88};
        selectSort(arr);
        System.out.println(Arrays.toString(arr));
    }


 public static void selectSort(int[] arr) {

        for (int i = 0; i < arr.length - 1; i++) {
            int minIndex = i;
            for (int j = i + 1; j < arr.length; j++) {
                if (arr[minIndex] > arr[j]) {
                    minIndex = j;
                }
            }
            // 交换
            int temp = arr[i];
            arr[i] = arr[minIndex];
            arr[minIndex] = temp;
        }
    }

    public static void swap(int []arr, int x, int y){
        int temp = arr[x];
        arr[x] = arr[y];
        arr[y] = temp;
    }

}

总结:比起版本1,交换的步骤要小

golang实现

int数组

package main

import (
	"fmt"
	"time"
)

func selectMax(arr[]int)int{
	length := len(arr);
	if length <= 0{
		return -404;
	}else if length == 1 {
		 return arr[0];
	}else{
		max := arr[0]; //假定第一个最大
		for i := 1; i < length; i++{
			if arr[i] > max { //任何一个比我的大的数,最大的
				max = arr[i]; // 更新最大值
			}
		}
		return max;
	}
}

// // 传递引用, 因此会改变原数组的值
func SelectSortMax(arr[] int) []int {
	length := len(arr);
    if length <= 1 {
		return arr;
	}else{
		for i := 0; i < length - 1 ; i++ { // 只剩下一个时不用挑选
			minIndex := i; // 假定当前索引为无序区间的最小值
			for j := i + 1; j < length; j++{ //向无需区间逼近
				if arr[j] < arr[minIndex] {
					minIndex = j;
				}
			}

			if minIndex != i {
				 arr[i], arr[minIndex] = arr[minIndex], arr[i];  //数据交换
			}
		}
		return arr;
	}
}
func main() {
	t := time.Now()

	arr:=[]int {1,9,2,8,3,7,4,6,5,10}
	fmt.Println(SelectSortMax(arr)) //[1 2 3 4 5 6 7 8 9 10]
	fmt.Println(arr) //[1 2 3 4 5 6 7 8 9 10]
	elapsed := time.Since(t)

	fmt.Println("app elapsed:", elapsed)
}


字符串数组

  • golang中的字符串排序
	fmt.Println("a">"b") // f
	fmt.Println("a"<"b") // t
	fmt.Println("a"=="a") //t

	pb:="a2"
	pa:="a1"
	fmt.Println("pa",&pa) //go1.1 ,1.3比较地址,go1.10 优化,比较字符串
	fmt.Println("pb",&pb)
	fmt.Println(pa<pb) //true
	fmt.Println("a1" <"a2") //true
	fmt.Println("ab" <"ac")//true
	fmt.Println("a1b" <"a1c")//true
  • go语言中由三种方法可以实现字符串的比较

go1.11.3比较地址,go1.10 优化,比较字符串
func main() {
  fmt.Println("a" < "b") //true
  pb := "b";
  pa := "a";
  fmt.Println(pa < pb) // true

  ppa := "a";
  ppb := "b";
  fmt.Println(ppa < ppb) // true

  //Compare 按字典顺序返回一个比较两个字符串的整数。如果 a == b,结果将为0,如果 a <b 则返回-1,如果 a> b 则返回+1。
  // Compare 仅包含与封装字节的对称性。使用内置的字符串比较运算符 ==,<,> 等通常会更清晰并且速度更快。
  // 先比较第一个元素,在比较第二个元素
  fmt.Println(strings.Compare("123", "12")) //1
  fmt.Println(strings.Compare("a1", "a12")) // -1


  //自建方法“==”,区分大小写
  fmt.Println("go"=="go", "GO"=="go")  // true, false
  fmt.Println("GO" < "go")  //  true

  //Compare函数,区分大小写
  fmt.Println(strings.Compare("GO","go")) // -1
  fmt.Println(strings.Compare("go","go")) // 0

  //比较UTF-8编码在小写的条件下是否相等,不区分大小写
  fmt.Println(strings.EqualFold("GO","go"))   // true
}

  • 自己实现的选择排序: 每次选择一个目标元素,插入到指定位置,然后到剩下的位置上选择一个目标元素,插入到指定位置:
package main

import (
	"fmt"
)

func SelectMaxString(arr []string) string{
	length := len(arr);
	if length == 0 {
		return "";
	}else if length == 1 {
		 return arr[0];
	}else{
		max := arr[0];
		for i := 1; i < length ; i++ {
			if arr[i] > max { // if strings.Compare(arr[min], arr[j]) > 0 {
				max = arr[i];
			}
		}
		return max;
	}
}


// // 传递引用, 因此会改变原数组的值
func SelectSortMax(arr[] string) []string {
	length := len(arr);
	if length <= 1 {
		return arr;
	}else{
		for i := 0; i < length - 1 ; i++ { // 只剩下一个时不用挑选
			minIndex := i; // 假定当前索引为无序区间的最小值
			for j := i + 1; j < length; j++{ //向无需区间逼近
				if arr[j] < arr[minIndex] { // strings.Compare(arr[min], arr[j]) > 0
					minIndex = j;
				}
			}

			if minIndex != i {
				arr[i], arr[minIndex] = arr[minIndex], arr[i];  //数据交换
			}
		}
		return arr;
	}
}

func main() {
	var arr []string = []string{"aaaws", "bbb", "Aaaa", "Abab", "d", "zzz", "BAaa", "12a", "223a"}
	fmt.Println(SelectSortMax(arr))
}

问题:

(1)选择排序的复杂度

选择排序的空间复杂度是O(1),是一种原地排序算法。选择排序的最好情况时间复杂度、最坏情况和平均情况时间复杂度都为 O(n )。

(2)选择排序是不是稳定的排序算法

不是,选择排序是一种不稳定的排序算法。选择排序每次都要找剩余未排序元素中的最小值,并和前面的元素交换位置,这样破坏了稳定性。

比如 5,8,5,2,9 这样一组数据,使用选择排序算法来排序的话,第一次找到最小元素2,与第一个 5 交换位置,那第一个 5 和中间的 5 顺序就变了,所以就不稳定了。正是因此,相对于冒泡排序和插入排序,选择排序就稍微逊色了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值