冒泡以及插入排序算法的改进

冒泡排序

说明:此文中的排序算法数组,第一个数(即0下标)没有作为数据处理(i从1开始),arr[0]用作哨岗,部分排序算法(如插入排序)比较时需要用到

排序思想:

1.假设共有N个数,从头开始,比较相邻的两个数,如果前一个数比后一个数大,则交换位置,否则不变,继续比较。

2.按照这样的方法对数组从0到N-1进行遍历,一轮遍历完,则最后一个数为最大值。

3.N=N-1,按照1,2的思想遍历N-1轮,则数组从大到小排序成功

void Popsort(int arr[],int n)//冒泡排序
{
    int i,j,temp;
    for(i = 1;i < n;i++)
    {
        for(j = 2;j < n - i + 1;j++) //注意:此处排序是从数组的下标1开始
        {
            if(arr[j-1] > arr[j])
            {
                temp = arr[j-1];
                arr[j-1] = arr[j];
                arr[j] = temp;
            }
        }
    }
}

下面对算法进行优化

改进版冒泡排序:

如果数组中有50个数,后20个已经有序且大于前面30个数,则一轮遍历完成,最后一个发生交换的位置肯定小于30,并且后面的数一定有序。

我们如果记下这个位置,然后遍历到此就结束此轮遍历比较,则算法会优化很多。

void PopsortPro(int arr[],int n)//改进版冒泡排序
{
    int i,exchange = n,temp;
    while(exchange)
    {
        n = exchange;
        exchange = 0;    //最后一次交换的位置置为0,若无交换,排序完成
        for(i = 2;i < n;i++)
        {
            if(arr[i-1] > arr[i])
            {
                temp = arr[i];
                arr[i] = arr[i-1];
                arr[i-1] = temp;
                exchange = i;        //记下最后一次交换的位置
            }
        }
    }
}

插入排序

排序思想:

1.把第一个数据当做有序的,即为有序区,后面的数据当做无序的,为无序区。

2.然后从无序数据中从第一个开始,不断按大小插入有序数据中。

3.i++,不断按2的方法循环,直到i==n-1,排序完成。

void InsertSort(int arr[],int n)//直接插入排序
{
    int i,k;
    for(i = 2;i < n;i++)
    {
        arr[0] = arr[i];        //arr[0]记录要插入的数
        k = i - 1;
        while(arr[k] > arr[0])    //找插入位置
        {
            arr[k+1] = arr[k];    //把数不停后移
            k--;
        }
        arr[k+1] = arr[0];
    }
}

改进版插入排序

因为插入的过程就是用无序区的数据在有序区做有序插入,其中就包含一个查找插入位置的过程,上述算法的查找方式为暴力查找,直接从尾部找到头部。

我们可以在查找插入位置的这一过程中做优化,使用效率更高的折半查找,可以优化算法效率。

上面的插入排序是边查找插入位置,边移动数据,如果利用折半查找插入位置,则是先找到位置,然后统一移动数据。

void Insert_halfsort(int arr[],int n)//折半插入排序
{
    int i,j,low,high,mid;
    for(i = 2;i < n;i++)
    {
        arr[0] = arr[i];
        high = i - 1;
        low = 1;
        while(low <= high)
        {
            mid = (low + high)/2;    //折半查找
            if(arr[mid] < arr[0])  //右半区域
            {
                low = mid + 1;
            }
            else                    //左半区域
            {
                high = mid - 1;
            }
        }                            //插入点即为high+1
        for(j = i;j > high+1;j--)    //将数据后移,空出位置填充无序数据
        {
            arr[j] = arr[j-1];
        }
        arr[high + 1] = arr[0];
    }
}

可以明显看到,利用折半查找的插入排序,代码量比直接插入排序多了一倍,不过在查找的过程中效率较高,数据移动个数是一致的。

不过这种优化没有什么大的改进,时间复杂度仍然是O(n^2)。

选择排序

这种算法和冒泡,插入排序效率差不多,时间复杂度都是O(n^2)。

冒泡排序主要操作在于交换,插入排序主要操作在于查找和移动数据,而选择排序则主要是大量的比较。

排序思想:

1.在一堆无序数据中通过遍历比较找到最小的数,放在第一个位置。

2.在剩下的无序数据中找到最小的数,放在第二个位置。

3.不断找到最小的数,最后一个最小值即放在最后一个位置。

void ChooseSort(int arr[],int n)//选择排序
{
    int i,j,min,temp;
    for(i = 1;i < n;i++)
    {
        min = i;
        for(j = i + 1;j < n;j++)
        {
            if(arr[j] < arr[min])
            {
                min = j;
            }
        }
        if(min != i)
        {
            temp = arr[min];
            arr[min] = arr[i];
            arr[i] = temp;
        }
    }
}

此算法没有想出什么优化的方法,就是不断在无序数据中找到最小值,而这个查找过程必须完全遍历。

时间: 2024-10-27 06:49:27

冒泡以及插入排序算法的改进的相关文章

C语言选择、冒泡、插入排序算法

#include <stdio.h> #pragma mark 选择排序算法 void xuanze_array(int *array, int len) { for (int i = 0; i<len-1; i++) { for (int j = i+1; j<len; j++) { if (array[i]<array[j]) { int temp = array[i]; array[i] = array[j]; array[j] = temp; } } } } #pra

排序系列 之 折半插入排序算法 —— Java实现

基本思想: 折半插入算法是对直接插入排序算法的改进,排序原理同直接插入算法: 把n个待排序的元素看成一个有序表和一个无序表,开始时有序表中只有一个元素,无序表中有n-1个元素:排序过程即每次从无序表中取出第一个元素,将它插入到有序表中,使之成为新的有序表,重复n-1次完成整个排序过程. 与直接插入算法的区别在于:在有序表中寻找待排序数据的正确位置时,使用了折半查找/二分查找. 实例: (参考直接插入排序算法:http://www.cnblogs.com/snowcan/p/6244128.htm

插入排序算法回顾(python实现)

插入排序的基本方法是:每步将一个待排序的记录按其关键字的大小插到前面已经排序的序列中的适当位置,直到全部记录插入完毕为止. 折半插入排序是对插入排序算法的一种改进,由于排序算法过程中,就是不断的依次将元素插入前面已排好序的序列中.由于前半部分为已排好序的数列,这样我们不用按顺序依次寻找插入点,可以采用折半查找的方法来加快寻找插入点的速度.具体操作为:在将一个新元素插入已排好序的数组的过程中,寻找插入点时,将待插入区域的首元素设置为a[low],末元素设置为a[high],则轮比较时将待插入元素与

“深入理解”—插入排序算法

总结下自己对插入排序的理解. 插入排序算法思想:每趟将一个元素,按照其关键字的大小插入到它前面已经排序的子序列中,依此重复,直到插入全部元素. 插入排序包括:直接插入排序.二分插入排序以及希尔排序. 1.直接插入排序: public void insert(int[] a) { for(int i=1;i<a.length;i++) //n-1此扫描,依次向前插入n-1个元素 { int temp=a[i]; //每趟将a[i]插入到前面的排序子序列中 int j; for(j=i-1;j>=

冒泡法的算法最佳情况下的时间复杂度为什么是O(n)

我在许多书本上看到冒泡排序的最佳时间复杂度是O(n),即是在序列本来就是正序的情况下. 但我一直不明白这是怎么算出来的,因此通过阅读<算法导论-第2版>的2.2节,使用对插入排序最佳时间复杂度推算的方法,来计算冒泡排序的复杂度. 1. <算法导论>2.2中对插入排序最佳时间复杂度的推算 在最好情况下,6和7总不被执行,5每次只被执行1次.因此, 时间复杂度为O(n) 2. 冒泡排序的时间复杂度 2.1 排序代码 public void bubbleSort(int arr[]) {

数据结构——排序——直接插入排序和折半插入排序算法

直接插入排序(Insertion Sort)的基本思想是: 每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的子序列中的适当位置,直到全部记录插入完成为止. 设数组为a[0…n-1]: 1. 初始时,a[0]自成1个有序区,无序区为a[1..n-1].令i=1 2. 将a[i]并入当前的有序区a[0…i-1]中形成a[0…i]的有序区间. 3. i++并重复第二步直到i==n-1.排序完成. #include<stdio.h> #include<stdbool.h> vo

插入排序算法之直接插入排序和希尔排序

插入排序算法 有一个已经有序的数据序列,要求在这个已经排好的数据序列中插入一个数,但要求插入后此数据序列仍然有序,这个时候就要用到一种新的排序方法--插入排序法,插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的.个数加一的有序数据. 直接插入排序 直接插入排序的排序思路是:每次将一个待排序的元素与已排序的元素进行逐一比较,直到找到合适的位置按大小插入. 例子: 有序列: 开始时,有序序列只有一个元素就是第一个元素(红色),后面的无序序列(绿色).接下来,取无序序列中

数据结构实践——归并排序算法的改进

本文是针对[数据结构基础系列(9):排序]的项目. [项目 - 归并排序算法的改进] 采用归并排序.快速排序等高效算法进行排序,当数据元素较少时(如n≤64),经常直接使用直接插入排序算法等高复杂度的算法.这样做,会带来一定的好处,例如归并排序减少分配.回收临时存储区域的频次,快速排序减少递归层次等. 试按上面的思路,重新实现归并排序算法. [参考解答] #include <stdio.h> #include <malloc.h> #include <stdlib.h>

插入排序---希尔插入排序算法(Javascript版)

取一个小于n的整数作为第一个增量,把序列分组.所有距离为增量的倍数的元素放在同一个组中.先在各组内进行直接插入排序:然后,取第二个增量(第二个<第一个)重复上述的分组和排序,直至所取的增量=1,即所有元素放在同一组中进行直接插入排序为止. 一般的初次取序列的一半为增量,以后每次减半,直到增量为1. 以下代码在nodejs中执行通过. function shellInsertSort(elements, di){ //从增量的所在位置开始 for(var i = di; i < elements