排序

1.冒泡排序

它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素列已经排序完成。      

关于代码实现,两层循环(若N个数排序),外层冒泡轮数(n-1),里层依次比较(n-i),时间复杂度为O(n2)。

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

 

冒泡有一个最大的问题就是这种算法不管不管你有序还是没序,闭着眼睛把你循环比较了再说。

针对这个问题,我们可以设定一个临时遍历来标记该数组是否已经有序,如果有序了就不用遍历了。

public static void sort(int arr[])
{
for( int i = 0;i < arr.length - 1 ; i++ )
{ boolean isSort
= true; for( int j = 0;j < arr.length - 1 - i ; j++ )
{
int temp = 0; if(arr[j] < arr[j + 1])
{ temp
= arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; isSort = false; } } if(isSort){ break; } } }

 

2.选择排序

选择排序的思路是这样的:首先,找到数组中最小的元素,拎出来,将它和数组的第一个元素交换位置,第二步,在剩下的元素中继续寻找最小的元素,拎出来,和数组的第二个元素交换位置,如此循环,直到整个数组排序完成。

public static void sort(int arr[]){
    for( int i = 0;i < arr.length ; i++ ){
        int min = i;//最小元素的下标
        for(int j = i + 1;j < arr.length ; j++ )
{
if(arr[j] < arr[min])
{ min
= j;//找最小值 } } //交换位置 int temp = arr[i]; arr[i] = arr[min]; arr[min] = temp; } }

 

双层循环,时间复杂度和冒泡一模一样,都是O(n2)。

 

 

3.插入排序

插入排序的思想和我们打扑克摸牌的时候一样,从牌堆里一张一张摸起来的牌都是乱序的,我们会把摸起来的牌插入到左手中合适的位置,让左手中的牌时刻保持一个有序的状态。

那如果我们不是从牌堆里摸牌,而是左手里面初始化就是一堆乱牌呢? 一样的道理,我们把牌往手的右边挪一挪,把手的左边空出一点位置来,然后在乱牌中抽一张出来,插入到左边,再抽一张出来,插入到左边,再抽一张,插入到左边,每次插入都插入到左边合适的位置,时刻保持左边的牌是有序的,直到右边的牌抽完,则排序完毕。

 

public static void sort(int[] arr) 
{
int n = arr.length; for (int i = 1; i < n; ++i)
{
int value = arr[i]; int j = 0;//插入的位置 for (j = i-1; j >= 0; j--)
{
if (arr[j] > value)
{ arr[j
+1] = arr[j];//移动数据(后移一位) }

else
{
break; } } arr[j+1] = value; //插入数据(这次进来的j+1相当于刚才的j) } }

 从代码里我们可以看出,如果找到了合适的位置,就不会再进行比较了,就好比牌堆里抽出的一张牌本身就比我手里的牌都小,那么我只需要直接放在末尾就行了,不用一个一个去移动数据腾出位置插入到中间。

最好情况的时间复杂度是 O(n),最坏情况的时间复杂度是 O(n2)

插入排序对于大规模的乱序数组的时候效率是比较慢的,因为它每次只能将数据移动一位

 

4.希尔排序

插入排序对于大规模的乱序数组的时候效率是比较慢的,因为它每次只能将数据移动一位,

 

希尔排序为了加快插入的速度,让数据移动的时候可以实现跳跃移动,节省了一部分的时间开支。

void shellSort(int a[], int n) {
    for (int step = n / 2; step > 0; step /= 2) {
        for (int i = step; i < n; ++i) {
            int j, val = a[i];
            for (j = n - step; j >= 0 && a[j] > val; j -= step) {
                a[j + step] = a[j];
            }
            a[j + 1] = val;
        }
    }
}

 

希尔排序在简单插入排序的基础上做了些改进,它的最好及最差时间复杂度和简单插入排序一样,分别是是O(n)和O(n2),平均时间复杂度试增量选取规则而定,一般认为介于O(n)和O(n2)之间。它不需要额外空间。它是不稳定的。


 

posted @ 2020-04-22 16:51  坦坦荡荡  阅读(128)  评论(0编辑  收藏  举报