GO、JAVA实现冒泡、选择、插入排序

5 篇文章 0 订阅
4 篇文章 0 订阅
本文介绍了冒泡、选择和插入三种排序算法的JAVA和GO语言实现。针对每种排序,文章详细阐述了算法原理,并通过实际运行效率对比展示了它们在处理大量数据时的表现。冒泡排序效率较低,而选择排序和插入排序相对更快,但时间复杂度均为O(n^2)。
摘要由CSDN通过智能技术生成

1. 冒泡排序

数组中每一个元素与其后一个元素进行比较,较大的或者较小的放在后面,即其与后面这个元素换位置。即第一个与第二个比,第二个与第三个比,知道倒数第二个与倒数第一个比,之后在数组的末尾就是最大或者最小的数了;之后继续上一个步骤,不过由于上一趟排序中,最后一个数已经为有序的,所以只需要比较到倒数第三个与倒数第二个比较;之后比较的次数逐次减少。

java代码
private void bubbling(int[] arr){
        for (int i = 0; i < arr.length - 1; i++){
            boolean hasChange = false;
            for (int j = 0; j < arr.length - i - 1; j++){
                if(arr[j] > arr[j + 1]){
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                    hasChange = true;
                }
            }
            if (!hasChange){
                break;
            }
        }
    }

效率问题:
慢…
进行80000个数字的排序,效率让人心碎:

public static void main(String[] args) {
        int[] arr = new int[80000];
        Random random = new Random();
        for (int i = 0; i < arr.length; i++){
            arr[i] = random.nextInt(800000);
        }
        SortDemo sortDemo = new SortDemo();
        System.out.println(System.currentTimeMillis());
        sortDemo.bubbling(arr);
        System.out.println(System.currentTimeMillis());
    }

输出如下:

1585325682398
1585325701677

19秒左右0.0

Go实现
func Bubbling(arr []int){
	for i := 0; i < len(arr) - 1; i++ {
		count := false
		for j := 0; j < len(arr) - i - 1; j++ {
			if (arr[j] > arr[j + 1]) {
				temp := 0
				temp = arr[j]
				arr[j] = arr[j + 1]
				arr[j + 1] = temp
				count = true
			}
		}
		if(!count){
			break;
		} 	
	}
}

效率问题:
也是一个慢字…毕竟冒泡 伤不起
80000个数字进行排序

func main(){
	arr := make([]int, 80000)
	t := time.Now()
	fomat := t.UnixNano()
	rand.Seed(fomat)
	for i := 0; i < len(arr); i++{
		arr[i] = rand.Intn(80000)
	}
	t1 := time.Now()
	Bubbling(arr)
	t2 := time.Since(t1)
	fmt.Println(t2)
}

输出如下:

15.9531755s

2. 选择排序

思路:从数组中选出一个最大(最小)值,放入数组头,或者数组尾,区别在于正向反向,全看自己心情,此处使用正向升序排序。每次找出最小值放入无序端的第一个,即第i个,i从0开始
废话不多说了,就是选出最小的往前放,上代码:

java实现
private void choice(int[] arr){
        for (int i = 0; i < arr.length - 1; i++){
            int min = arr[i];
            int minIndex = i;
            for (int j = i + 1; j < arr.length; j++){
                if (arr[j] < min){
                    min = arr[j];
                    minIndex = j;
                }
            }
            if (i != minIndex){
                int temp = arr[i];
                arr[i] = arr[minIndex];
                arr[minIndex] = temp;
            }
        }
    }

效率问题:比起冒泡是好了不少,但时间复杂度还是O(n^2)
依然是那熟悉的80000比数据

  public static void main(String[] args) {
        int[] arr = new int[80000];
        Random random = new Random();
        for (int i = 0; i < arr.length; i++){
            arr[i] = random.nextInt(800000);
        }
        SortDemo sortDemo = new SortDemo();
        System.out.println(System.currentTimeMillis());
        sortDemo.choice(arr);
        System.out.println(System.currentTimeMillis());
    }

输出结果:

1585326261907
1585326268503

7秒左右,确实比老爷爷冒泡跑的快了点

Go实现
func choice(arr []int){
	for i := 0; i < len(arr) - 1; i++{
		min := arr[i]
		minIndex := i
		for j := i + 1; j < len(arr); j++{
			if (arr[j] < min){
				min = arr[j]
				minIndex = i
			}
		}
		if (i != minIndex){
			temp := arr[i]
			arr[i] = arr[minIndex]
			arr[minIndex] = temp
		}
	}
}

再以80000比数据跑一遍:

func main(){
	arr := make([]int, 80000)
	t := time.Now()
	fomat := t.UnixNano()
	rand.Seed(fomat)
	for i := 0; i < len(arr); i++{
		arr[i] = rand.Intn(80000)
	}
	t1 := time.Now()
	choice(arr)
	t2 := time.Since(t1)
	fmt.Println(t2)
}

输出如下:

6.6854358s

和java兄弟并排走,时间差不多

3. 插入排序

插入排序的思想是,将数组分为两部分,左边为有序部分,右边为无序部分。每次从无序部分取出第一个,与有序部分分别比较,并将其插入到有序部分中,至此,有序部分加一,无序部分减一。当无序部分长度减为0时,整个数组都为有序了
如何插入?
如何理解插入这个命名呢,我们定义insertIndex为待被插入的下标,如果我们当前采用的比较的数比arr[insertIndex]小(假设是升序排列),那么将arr[insertIndex]向后放,即有如下数组:

[3, 1, 2]

我们选1作为insertValueinsertIndex为0,那么此时比较发现 arr[insertIndex] > insertValue,那么我们把3提起来往后放,放到arr[insertIndex + 1]的位置,之后再往前比,发现已经到了最前,就可以将arr[insertIndex] = insertValue;只是举了一个简单的例子,如果是:

[2, 3, 4, 5, 1]

我们此时遍历到最后一个元素,即1,此时insertValue = 1insertIndex = 3,那么如下就是该数组的更改顺序:

1. [2, 3, 4, 5, 5] insertValue = 1 insertIndex = 3
2. [2, 3, 4, 4, 5] insertValue = 1 insertIndex = 2
3. [2, 3, 3, 4, 5] insertValue = 1 insertIndex = 1
4. [2, 2, 3, 4, 5] insertValue = 1 insertIndex = 0
5. [1, 2, 3, 4, 5] 最后当  insertIndex = 0 时,给 arr[insertIndex] = insertValue
具体分析
int insertValue = arr[1] //需要插入进去的值
Int insertIndex = 1 -1 //将要被插入的元素的前一个元素的下标
while(insertIndex >= 0 && insertValue < arr[insertIndex]){
//上述判断: 当元素被插入进有序部分后,如果他前面的待被插入元素仍大于等于0,	说明它前面仍然有元素
//当被插入元素的值小于它前面待被插入的元素,说明它现在没有和目前的前一个元素比较过,
//仍然没有确定位置,所以需要再进行比较,当它前面没有元素或者它前面的元素的值小于它,说明它已经正确插入了有序部分
//只要进入循环,说明它已经执行了一次插入动作,插入的实现为将待插入的元素与前面的元素换位
arr[insertIndex + 1] = arr[insertIndex]
//当换位后,目前待被插入的元素就是目前其所在位置的前一个了,
//因为该元素向前插入了一个位置,所以待被插入的元素位置也向前移动
insertIndex --
}
//因为上述循环中,如果在最后一次循环,插入元素的前面并没有元素了,或者前一个元素比它小,但是
//insertIndex仍然减一了 所以,待插入的元素的正确位置应该是insertIndex+1
arr[insertIndex + 1] = insertValue

在插入排序中,我们在刚开始时总认为第一个元素自己组成了有序部分,因为也没有其他元素和他比较大小。所以无序部分的第一个起始为1,之后每次向后加,我们只需要给这个步骤加一个循环即可;

java实现
private void insertSort(int[] arr){
        //循环表示第几个被插入的数  从1开始
        for (int i = 1; i < arr.length; i++){
            //需要插入的数为
            int insertValue = arr[i];
            //待被插入的下标  在待插入数的前一个
            int insertIndex = i - 1;
            //insertIndex >= 0 当insertIndex小于0时,说明待插入数之前已经没有数据了,它是最小的数
            //insertValue < arr[insertIndex] 当待插入的数小于前一个数时,还不知道它是不是最小,它还需要与它前前一个进行
            //比较,但是在此时他已经可以插队到他前一个数之前
            while (insertIndex >= 0 && insertValue < arr[insertIndex]){
                // 将当前的位置的数向后移动一位
                arr[insertIndex + 1] = arr[insertIndex];
                // 将下标值减一,表示将要与当前位置的前一个位置比较
                insertIndex--;
            }
            arr[insertIndex + 1] = insertValue;
        }
    }

效率分析:

public static void main(String[] args) {
        int[] arr = new int[80000];
        Random random = new Random();
        for (int i = 0; i < arr.length; i++){
            arr[i] = random.nextInt(800000);
        }
        SortDemo sortDemo = new SortDemo();
        System.out.println(System.currentTimeMillis());
        sortDemo.insertSort(arr);
        System.out.println(System.currentTimeMillis());
    }
1585326807369
1585326809251

比起选择排序更快

Go实现
func insertSort(arr []int){
	for i := 1; i < len(arr); i++{
		insertValue := arr[i]
		insertIndex := i - 1
		for {
			if (insertIndex < 0 || insertValue > arr[insertIndex]){
				break
			}
			arr[insertIndex + 1] = arr[insertIndex]
			insertIndex--
		}
		arr[insertIndex + 1] = insertValue
	}
}

执行效率:

func main(){
	arr := make([]int, 80000)
	t := time.Now()
	fomat := t.UnixNano()
	rand.Seed(fomat)
	for i := 0; i < len(arr); i++{
		arr[i] = rand.Intn(80000)
	}
	t1 := time.Now()
	insertSort(arr)
	t2 := time.Since(t1)
	fmt.Println(t2)
}

执行结果:

1.8607944s

如果走的不快,那就多走几步。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值