【数据结构与算法】从0-1小白学习之路(进阶篇)

版权声明:如有转载-请加微信457556886告知下就可以 知识都是分享的 https://blog.csdn.net/wolf_love666/article/details/90815450

算法的分类:

  • 根据时间复杂度分类
  • 根据稳定性分类
  • 其他比如鸡尾酒排序,猴子排序,睡眠排序。

常用算法:
在这里插入图片描述

冒泡排序以及4种算法优化
冒泡排序顾名思义就是整个过程像气泡一样往上升,单向冒泡排序的基本思想是(假设由小到大排序):对于给定n个记录,从第一个记录开始依次对相邻的两个记录进行比较,当前面的记录大于后面的记录时,交换位置,进行一轮比较和换位后,n个记录的最大记录将位于第n位,然后对前(n-1)个记录进行第二轮比较;重复该过程,直到记录剩下一个为止。

  • 基础: 两层for循环,外层控制所有次数执行,内层控制所有数据交换排序。
   //1-基础冒泡排序
    public static void bubbleSort_1(int [] intarr){
        //冒泡排序
        //先进行所有元素迭代遍历
        int count = 0;
        //由于两两比较,则肯定是有个数不需要比较的所以这里需要减去1
        for (int i = 0;i < intarr.length-1;i++){
            //比较其中的每一个元素element,由于冒泡排序是下沉的小数在前,
            大数在后,先下沉大数,
            则每次外部循环的次数正好是已经排序好的不需要再排序的,所以这里是需要减去已经排好序的,由于i=0开始,那么不需要自己相比较,所以j从1开始。
            for(int j = 1;j < intarr.length - i;j++){
                //如果当前的元素>之后比较的元素,则交换位置,
                将小的元素放至在当前的元素的位置
                if(intarr[j-1]>intarr[j]){
                    int temp = intarr[j-1];
                    intarr[j-1] = intarr[j];
                    intarr[j] = temp;

                }
                count++;
                //假设数组2,3,1
                //则arr[0]=2与arr[1],比较,小于则通过,与arr[2]比较,大于则交换,arr[0]=1,arr[2]=3.则经历过第一次循环以后,{1,3,2}
                //则arr[1]=3与arr[1],比较,等于则通过,与arr[2]比较,大于则交换,arr[1]=2,arr[2]=3,则经历过第二次循环以后,{1,2,3}
                //第三次循环,arr[2]=2与arr[1],比较,等于则通过,与arr[2]比较,小于则通过,所以最终顺序为{1,2,3}
            }
            System.out.println("bubbleSort_1::"+Arrays.toString(intarr));
        }
        System.out.println("bubbleSort_1比较次数:"+count);
    }

在这里插入图片描述

当最好的情况,也就是要排序的序列本身就是有序的,需要进行(n-1)次比较,没有数据交换,时间复杂度为O(n).
当最坏的情况,即待排序的表是逆序的情况,此时需要比较次数为:1+2+3+…+(n-1)=n(n-1)/2 次,并作等数量级的记录移动,因此总的时间复杂度为O(n2)

  • 优化1:对于已经排序过的无需排序,标记为sorted,减少多余排序比较(如果是完全逆序的情况下,则和上面的基础排序没有区别)
//2-增加标记冒泡排序
    public static void bubbleSort_2(int [] intarr){
        //根据上面的冒泡排序我们知道其中我们每次遍历的时候都进行了所有的元素的比较
        //那么我们可以增加标记,减少不必要的重复比较
        int k = intarr.length;
        boolean sorted = true;
        int count = 0;
        //循环遍历
        while(sorted){
            //首次进入的时候我们需要设置为未排序过
            sorted = false;
            //交换一遍顺序
            for (int i = 1;i < k ;i++){
                if (intarr[i-1] > intarr[i]){
                    int temp = intarr[i-1];
                    intarr[i-1] = intarr[i];
                    intarr[i] = temp;
                    sorted = true;
                }
                count++;
            }
            System.out.println("bubbleSort_2::"+Arrays.toString(intarr));
            k--;
        }
        System.out.println("bubbleSort_2比较次数:"+count);
    }
  • 优化2:基于上面讲每次无序遍历的内层循环更新为最后一层交换元素的位置,减少一些已经排序好的比较(假设都是无序状态,则与上面的优化1没有区别甚至可能不如优化1,如果后面都是有序,例如{1,5,4,8,9,42,5,7,7,8,9,10,11,12})
 public static void bubbleSort_3(int [] intarr) {
    //基于上面讲每次无序遍历的内层循环更新为最后一层交换元素的位置,
    减少一些已经排序好的比较、、
    假设我们前面大部分是无序的,后面是有序的
//(1,2,5,7,4,3,6,8,9,10)这种场景,
则我们可以记录最后一次的交换位置,
下一次排序从第一个比较到上次记录的位置就可以了
        //所以基于以上的排序算法更改如下,初始化尾边界
        int tailBorder = intarr.length;
        int count = 0;
        int length = 0;
        while(tailBorder > 0){//尾边界排序未结束
            //遍历两两比较和交换位置
            length = tailBorder;
            tailBorder = 0;
            for (int i = 1;i < length;i++) {
                if (intarr[i-1] > intarr[i]){
                    int temp = intarr[i-1];
                    intarr[i-1] = intarr[i];
                    intarr[i] = temp;
                    tailBorder = i;
                }
                //假设已经排序好了m个,后面n个待排序

                count++;
            }

            System.out.println("bubbleSort_3::"+Arrays.toString(intarr));

        }

        System.out.println("bubbleSort_3比较次数:"+count);
    }

基础比较次数91次,优化1比较次数46次,优化2比较次数37次,优化3比较次数16次
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 优化3:鸡尾酒排序实现思路:外层循环所有元素,内层一共2套逻辑,第一套逻辑从左向右比较,第二套从右向左比较,类似钟摆一样来回比较。缺点是代码增多,适用场景是大部分有序的情况下。
 //鸡尾酒的排序实现
    public static void bubbleSort_4(int [] intarr) {
        //外层循环所有元素
        int count = 0;
        boolean sorted = false;//初始是没有排序
        for (int i = 0; i < intarr.length/2;i++){
            //left->right比较
            System.out.println("bubbleSort_4:left->right 比较前:"+Arrays.toString(intarr));
            for (int j = i;j < intarr.length - 1 - i;j++){
                if (intarr[j] > intarr [j+1]){
                    int temp = intarr[j];
                    intarr[j] = intarr[j+1];
                    intarr[j+1] = temp;
                    sorted = true;
                    count++;
                }
            }

            System.out.println("bubbleSort_4:left->right 比较后:"+Arrays.toString(intarr));
            //right->left比较

            System.out.println("bubbleSort_4:right->left 比较前:"+Arrays.toString(intarr));
            for (int j = intarr.length - 1 - i;j > i;j--){
                if (intarr[j-1] > intarr [j]){
                    int temp = intarr[j-1];
                    intarr[j-1] = intarr[j];
                    intarr[j] = temp;
                    sorted = true;
                    count++;
                }
            }
            //如果是排序完成或者排序好的则退出

            System.out.println("bubbleSort_4:right->left 比较后:"+Arrays.toString(intarr));
            if (sorted == false){
                break;
            }
        }

        System.out.println("bubbleSort_4比较次数:"+count);
    }

在这里插入图片描述

计数排序
适用场景:当数列最大和最小值差距不大,当数列元素是整数时候。

桶排序

  • 求数列最大最小值,运算量为n
  • 创建空桶,运算量为n
  • 把原始数列的元素分配到各个桶中,运算量为n
  • 每个通内部排序,元素分布相对均匀情况下,所有桶运算量之和为n
  • 输出排序数列,运算量为n

快速排序
堆排序
归并排序
二分查找
线性查找
深度优先
广度优先
Dijkstra
动态规划
朴素贝叶斯

猜你喜欢

转载自blog.csdn.net/wolf_love666/article/details/90815450