基础算法分析及优化方法(冒泡、选择、插入,盘点面试的时候可能遇到的问题)

一、冒泡算法

冒泡算法的一个重点特征是:体现冒泡的过程,大的沉底,小的上浮

曾经忽略这个过程,面试被考到了。

假定数组下标为[0,1,...,n]

  1. 首先从第一个数据开始,与第二个数据相比,若大于第二个数据,则将两个数据的位置进行交换

  2. 将指针由第一个数据指向第二个数据,比较第二个数据与第三个数据,如果第二数据比第三个数据大,则交换第二个数据与第三个数据的位置。

  3. 以此类推,完成第一轮排序(指针指向 n-1 )后,最大的数据被“”到末尾

  4. 按照上面的过程进行第二遍排序,完成排序后(指针指向 n-2 )后,第二大的数据被放到倒数第二的位置

  5. 重复上述过程,每排序完成一次,比较次数就减少一次。

Example:

input: 5, 4, 6, 7, 1

第一轮排序:指针指向 5,4 与 5 比较, 5 > 4, 进行位置交换, 结果为: 45, 6, 7, 1

                      指针指向 5,  5 与 6 比较, 5 < 6, 不进行位置交换, 结果为: 4, 5, 6, 7, 1 

                      指针指向 6,  6 与 7 比较, 6 < 7, 不进行位置交换, 结果为: 4, 5, 6, 7, 1

                      指针指向 7,  7 与 1 比较, 7 > 1, 进行位置交换, 结果我:4, 5, 6, 1, 7

第一趟完成排序后,最大的数据 7 被 “”到末尾的位置了

第二轮排序,我们要将第二大的数据,放到倒数第二的位置,所以结果为:4, 5, 1, 6, 7

第三轮排序结果:4, 1, 5, 6, 7

第四轮排序结果:1, 4, 5, 6, 7

最终的排序结果为 1, 4, 5, 6, 7

分析:由上可知使用冒泡法对 N个数据进行排序,需要进行 N-1 轮排序,第“i”轮要比较的次数为 N-i

则整个冒泡排序过程需要比较的次数为:N-1 + N-2 + N-3 + ... + 1 = 1/2 * (N-1) * (1+N-1) = 1/2 * (N^2-N)

最大需要交换的次数为:N-1 + N-2 + N-3 + ... + 1 = 1/2 * (N-1) * (1+N-1) = 1/2 * (N^2-N)

时间复杂度 :O(n*n)

示例代码:

for(int i = 0; i < length-1; i++){        //限定排序轮数 N-1
    for(int j = 0; j < length-1-i; j++){    //每轮比较次数 N-i(i从0开始)
        if(nums[j] > nums[j+1]){
            int temp = nums[j];
            nums[j] = num[j+1];
            nums[j+1] = temp;
        }
    }
}

在不改变算法的情况下,对冒泡法进行优化

看到这个要求,可能会没什么头绪,脑子里浮现的东西都是把冒泡法改变成其他算法,但是这里我们可以先从算法过程分析,我们在循环内部只做两件事情,判断条件交换数据。要优化只能减少不必要的 判断 或者 交换数据。从实现角度我们只能从减少不要的判断出发。当数据已有序时,我们就可以略去这个判断的过程。

方法一:外层循环优化

// BbBBleSort01
for(int i = 0; i < length - 1; i++){
    boolean flag = true;                        //假定每次要排序的数据有序
    for(int j = 0; j < length - 1 - i; j++){
        if(nums[j] > nums[j+1]){
            int temp = nums[j];
            nums[j] = nums[j+1];
            nums[j+1] = nums[j];
            flag = false;                       //执行交换说明数据无序                    
        }
    }
    if(flag)                                    //某趟排序时发现数组有序,跳过后面排序
        break;
}
  1. 每轮循环开始前设置一个 flag = true;

  2. 当该轮循环没有执行一次交换数据操作,说明全部数据有序,直接跳出循环

  3. 否则下一轮循环,直至有序

方法二:内层循环优化

//BubbleSort02
int index = length-1;
for(int i = 0; i < length - 1; i++){
    boolean flag = true;                //假定数组有序
    int n = 0;                          //用于数组无序时,储存当前指针位置
    for(int j = 0; j < index; j++){
        if(nums[j] > nums[j+1]){
            int temp = nums[j];
            nums[j] = nums[j+1];
            nums[j+1] = temp;
            flag = false;               //执行数据交换,数组无序
            n = j;                      //记录每次交换的下标,一轮排序后为最后无序的下标
        }
    }
    if(flag)                                
        break;
    index = n;                          //下次排序只排序无序部分
}
  1. 每轮循环开始时设置一个 flag(判断是否有序) 和 n 记录无序数据的范围

  2. 当执行交换操作时,说明无序,并记录下标

  3. 若数据无序,则下次循环只排序无序部分[0, ... ,n]


二、选择排序

 选择排序时对冒泡排序的改进,它的改进之处正是在冒泡排序的交换次数上(所以前面对冒泡排序的优化没有改变这一点,不然就变成选择排序了)。基本选择排序与基本冒泡排序的比较次数相同,但交换次数要小于冒泡排序。所以当数据量较大时,效率会有明显的提升。

选择排序的重要特征是:体现出一个选择的过程,选出需要的那个数据再进行交换

假定数组下标为[0,1,...,n]

  1. 从第一个元素开始,分别于后面的元素相比较,找到最小的元素与第一个元素交换位置

  2. 从第二个元素开始,分别于后面的元素相比较,查到剩余元素中的最小元素,与第二个元素交换位置

  3. 重复上述步骤,值到所有的元素都按从小到大的顺序排列位置

Example:

input: 8, 6, 4, 7, 1

第一轮排序:指针指向 8 ,将 6 与 8 相比,选出小的元素 6

                                            将 6 与 4 相比,选出小的元素 4

                                            将 4 与 7 相比, 选出小的元素 7

                                            将 7 与 1 相比, 选出小的元素 1,将 8 与 1 交换位置 结果为:1, 6, 4, 7, 8

第二轮排序:指针指向 6 ,选择 6, 4, 7, 8 中的最小元素 4,将 4 与 6交换位置,结果为:1, 4, 6, 7, 8

第三轮排序:指针指向 6 ,选出 6, 7, 8 中的最小元素 6 ,不做位置交换,结果为:1, 4, 6, 7, 8

第四轮排序:指针指向 7,选出 7, 8 中的最小元素 7,不做位置交换,结果为:1, 4, 6, 7, 8

所以排序结果为: 1, 4, 6, 7, 8

分析:由上可知,选择排序每排序完一轮都把最小的元素移到了已排序部分的末尾,然后下一轮的比较次数比上一轮减少一次,即第 i 轮排序需要比较N-1次,因此,N 个数据进行选择排序,需要排序 N-1 轮,第 i 轮需要比较 N-1

则选择排序需要判断的次数为:N-1 + N-2 + N-3 + ... + 1 = 1/2 * (N-1) * (1+N-1) = 1/2 * (N^2-N)

需要交换的次数为:N-1

时间复杂度:O(n*n)

示例代码:

int minIndex = 0;                        // 记录最小元素的下标
int temp = 0;                        
for(int i = 0; i < nums.length; i++){
    minIndex = i;
    for(int j = i+1; j < nums.length;){
        if(nums[j] < nums[minIndex])
            minIndex = j;
    } 
    temp = nums[i];
    nums[i] = nums[minIndex];
    nums[minIndex] = temp;
}

优化

猜你喜欢

转载自blog.csdn.net/qq_38959715/article/details/82662413
今日推荐