数组的常见算法

数组的常见算法

 数值型数组特征值统计

  • 这里的特征值涉及到:平均值、最大值、最小值、总和等

举例1:数组统计:求总和、均值

public class TestArrayElementSum {
    public static void main(String[] args) {
        int[] arr = {4,5,6,1,9};
        //求总和、均值
        int sum = 0;//因为0加上任何数都不影响结果
        for(int i=0; i<arr.length; i++){
            sum += arr[i];
        }
        double avg = (double)sum/arr.length;
​
        System.out.println("sum = " + sum);
        System.out.println("avg = " + avg);
    }
}

举例2:求数组元素的总乘积

public class TestArrayElementMul {
    public static void main(String[] args) {
        int[] arr = {4,5,6,1,9};
​
        //求总乘积
        long result = 1;//因为1乘以任何数都不影响结果
        for(int i=0; i<arr.length; i++){
            result *= arr[i];
        }
​
        System.out.println("result = " + result);
    }
}

举例3:求数组元素中偶数的个数

public class TestArrayElementEvenCount {
    public static void main(String[] args) {
        int[] arr = {4,5,6,1,9};
        //统计偶数个数
        int evenCount = 0;
        for(int i=0; i<arr.length; i++){
            if(arr[i]%2==0){
                evenCount++;
            }
        }
​
        System.out.println("evenCount = " + evenCount);
    }
}

举例4:求数组元素的最大值

public class TestArrayMax {
    public static void main(String[] args) {
        int[] arr = {4,5,6,1,9};
        //找最大值
        int max = arr[0];
        for(int i=1; i<arr.length; i++){//此处i从1开始,是max不需要与arr[0]再比较一次了
            if(arr[i] > max){
                max = arr[i];
            }
        }
​
        System.out.println("max = " + max);
    }
}

举例5:找最值及其第一次出现的下标

public class TestMaxIndex {
    public static void main(String[] args) {
        int[] arr = {4,5,6,1,9};
        //找最大值以及第一个最大值下标
        int max = arr[0];
        int index = 0;
        for(int i=1; i<arr.length; i++){
            if(arr[i] > max){
                max = arr[i];
                index = i;
            }
        }
​
        System.out.println("max = " + max);
        System.out.println("index = " + index);
    }
}

举例6:找最值及其所有最值的下标

public class Test13AllMaxIndex {
    public static void main(String[] args) {
        int[] arr = {4,5,6,1,9,9,3};
        //找最大值
        int max = arr[0];
        for(int i=1; i<arr.length; i++){
            if(arr[i] > max){
                max = arr[i];
            }
        }
        System.out.println("最大值是:" + max);
        System.out.print("最大值的下标有:");
​
        //遍历数组,看哪些元素和最大值是一样的
        for(int i=0; i<arr.length; i++){
            if(max == arr[i]){
                System.out.print(i+"\t");
            }
        }
        System.out.println();
    }
}

优化

public class Test13AllMaxIndex2 {
    public static void main(String[] args) {
        int[] arr = {4,5,6,1,9,9,3};
        //找最大值
        int max = arr[0];
        String index = "0";
        for(int i=1; i<arr.length; i++){
            if(arr[i] > max){
                max = arr[i];
                index = i + "";
            }else if(arr[i] == max){
                index += "," + i;
            }
        }
​
        System.out.println("最大值是" + max);
        System.out.println("最大值的下标是[" + index+"]");
    }
}

举例7(难):输入一个整形数组,数组里有正数也有负数。数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。求所有子数组的和的最大值。要求时间复杂度为O(n)。 例如:输入的数组为1, -2, 3, -10, -4, 7, 2, -5,和最大的子数组为3, 10, -4, 7, 2,因此输出为该子数组的和18。

public class Test5 {
    public static void main(String[] args) {
        int[] arr = new int[]{1, -2, 3, 10, -4, 7, 2, -5};
        int i = getGreatestSum(arr);
        System.out.println(i);
    }
    
    public static int getGreatestSum(int[] arr){
        int greatestSum = 0;
        if(arr == null || arr.length == 0){
            return 0;
        }
        int temp = greatestSum;
        for(int i = 0;i < arr.length;i++){
            temp += arr[i];
            
            if(temp < 0){
                temp = 0;
            }
            
            if(temp > greatestSum){
                greatestSum = temp;
            }
        }
        if(greatestSum == 0){
            greatestSum = arr[0];
            for(int i = 1;i < arr.length;i++){
                if(greatestSum < arr[i]){
                    greatestSum = arr[i];
                }
            }
        }
        return greatestSum;
    }
}

举例8:评委打分

分析以下需求,并用代码实现:

(1)在编程竞赛中,有10位评委为参赛的选手打分,分数分别为:5,4,6,8,9,0,1,2,7,3

(2)求选手的最后得分(去掉一个最高分和一个最低分后其余8位评委打分的平均值)

/**
 * @author 尚硅谷-宋红康
 * @create 10:03
 */
public class ArrayExer {
    public static void main(String[] args) {
        int[] scores = {5,4,6,8,9,0,1,2,7,3};
​
        int max = scores[0];
        int min = scores[0];
        int sum = 0;
        for(int i = 0;i < scores.length;i++){
            if(max < scores[i]){
                max = scores[i];
            }
​
            if(min > scores[i]){
                min = scores[i];
            }
​
            sum += scores[i];
        }
​
        double avg = (double)(sum - max - min) / (scores.length - 2);
​
        System.out.println("选手去掉最高分和最低分之后的平均分为:" + avg);
    }
}

数组元素的赋值与数组复制

举例1:杨辉三角(见二维数组课后案例)

举例2:使用简单数组

(1)创建一个名为ArrayTest的类,在main()方法中声明array1和array2两个变量,他们是int[]类型的数组。

(2)使用大括号{},把array1初始化为8个素数:2,3,5,7,11,13,17,19。

(3)显示array1的内容。

(4)赋值array2变量等于array1,修改array2中的偶索引元素,使其等于索引值(如array[0]=0,array[2]=2)。打印出array1。 array2 = array1;

思考:array1和array2是什么关系?

拓展:修改题目,实现array2对array1数组的复制

举例3:一个数组,让数组的每个元素去除第一个元素,得到的商作为被除数所在位置的新值。

public class Test3 {
    public static void main(String[] args) {
        int[] arr = new int[]{12,43,65,3,-8,64,2};
        
//      for(int i = 0;i < arr.length;i++){
//          arr[i] = arr[i] / arr[0];
//      }
        for(int i = arr.length -1;i >= 0;i--){
            arr[i] = arr[i] / arr[0];
        }
        //遍历arr
        for(int i = 0;i < arr.length;i++){
            System.out.print(arr[i] + " ");
        }
    }
}

举例4:创建一个长度为6的int型数组,要求数组元素的值都在1-30之间,且是随机赋值。同时,要求元素的值各不相同。

public class Test4 {
    // 5-67 Math.random() * 63 + 5;
    @Test
    public void test1() {
        int[] arr = new int[6];
        for (int i = 0; i < arr.length; i++) {// [0,1) [0,30) [1,31)
            arr[i] = (int) (Math.random() * 30) + 1;
​
            boolean flag = false;
            while (true) {
                for (int j = 0; j < i; j++) {
                    if (arr[i] == arr[j]) {
                        flag = true;
                        break;
                    }
                }
                if (flag) {
                    arr[i] = (int) (Math.random() * 30) + 1;
                    flag = false;
                    continue;
                }
                break;
            }
        }
​
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }
    //更优的方法
    @Test
    public void test2(){
        int[] arr = new int[6];
        for (int i = 0; i < arr.length; i++) {// [0,1) [0,30) [1,31)
            arr[i] = (int) (Math.random() * 30) + 1;
            
                for (int j = 0; j < i; j++) {
                    if (arr[i] == arr[j]) {
                        i--;
                        break;
                    }
                }
            }
​
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }
}

举例5:扑克牌

案例:遍历扑克牌

遍历扑克牌,效果如图所示:

提示:使用两个字符串数组,分别保存花色和点数,再用一个字符串数组保存最后的扑克牌。 String[] hua = {"黑桃","红桃","梅花","方片"}; String[] dian = {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};

package com.atguigu3.common_algorithm.exer5;
​
/**
 * @author 尚硅谷-宋红康
 * @create 17:16
 */
public class ArrayExer05 {
    public static void main(String[] args) {
        String[] hua = {"黑桃","红桃","梅花","方片"};
        String[] dian = {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
​
​
        String[] pai = new String[hua.length * dian.length];
        int k = 0;
        for(int i = 0;i < hua.length;i++){
            for(int j = 0;j < dian.length;j++){
                pai[k++] = hua[i] + dian[j];
            }
        }
​
        for (int i = 0; i < pai.length; i++) {
            System.out.print(pai[i] + "  ");
            if(i % 13 == 12){
                System.out.println();
            }
        }
​
    }
}
​

拓展:在上述基础上,增加大王、小王。

举例6:回形数

从键盘输入一个整数(1~20) ,则以该数字为矩阵的大小,把1,2,3…n*n 的数字按照顺时针螺旋的形式填入其中。

例如: 输入数字2,则程序输出: 1 2 4 3

输入数字3,则程序输出: 1 2 3 8 9 4 7 6 5 输入数字4, 则程序输出: 1 2 3 4 12 13 14 5 11 16 15 6 10 9 8 7

//方式1
public class RectangleTest {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("输入一个数字");
        int len = scanner.nextInt();
        int[][] arr = new int[len][len];
        
        int s = len * len;
        /*
         * k = 1:向右
         * k = 2:向下
         * k = 3:向左
         * k = 4:向上
         */
        int k = 1;
        int i = 0,j = 0;
        for(int m = 1;m <= s;m++){
            if(k == 1){
                if(j < len && arr[i][j] == 0){
                    arr[i][j++] = m;
                }else{
                    k = 2;
                    i++;  
                    j--;
                    m--;
                }
            }else if(k == 2){
                if(i < len && arr[i][j] == 0){
                    arr[i++][j] = m;
                }else{
                    k = 3;
                    i--;
                    j--;
                    m--;
                }
            }else if(k == 3){
                if(j >= 0 && arr[i][j] == 0){
                    arr[i][j--] = m;
                }else{
                    k = 4;
                    i--;
                    j++;
                    m--;
                }
            }else if(k == 4){
                if(i >= 0 && arr[i][j] == 0){
                    arr[i--][j] = m;
                }else{
                    k = 1;
                    i++;
                    j++;
                    m--;
                }
            }
        }
        
        //遍历
        for(int m = 0;m < arr.length;m++){
            for(int n = 0;n < arr[m].length;n++){
                System.out.print(arr[m][n] + "\t");
            }
            System.out.println();
        }
    }
}
//方式2
/*
    01 02 03 04 05 06 07 
    24 25 26 27 28 29 08 
    23 40 41 42 43 30 09 
    22 39 48 49 44 31 10 
    21 38 47 46 45 32 11 
    20 37 36 35 34 33 12 
    19 18 17 16 15 14 13 
 */
public class RectangleTest1 {
​
    public static void main(String[] args) {
        int n = 7;
        int[][] arr = new int[n][n];
        
        int count = 0; //要显示的数据
        int maxX = n-1; //x轴的最大下标
        int maxY = n-1; //Y轴的最大下标
        int minX = 0; //x轴的最小下标
        int minY = 0; //Y轴的最小下标
        while(minX<=maxX) {
            for(int x=minX;x<=maxX;x++) {
                arr[minY][x] = ++count;
            }
            minY++;
            for(int y=minY;y<=maxY;y++) {
                arr[y][maxX] = ++count;
            }
            maxX--;
            for(int x=maxX;x>=minX;x--) {
                arr[maxY][x] = ++count;
            }
            maxY--;
            for(int y=maxY;y>=minY;y--) {
                arr[y][minX] = ++count;
            }
            minX++;
        }
        
        
        for(int i=0;i<arr.length;i++) {
            for(int j=0;j<arr.length;j++) {
                String space = (arr[i][j]+"").length()==1 ? "0":"";
                System.out.print(space+arr[i][j]+" ");
            }
            System.out.println();
        }
    }
}

数组元素的反转

实现思想:数组对称位置的元素互换。

public class TestArrayReverse1 {
    public static void main(String[] args) {
        int[] arr = {1,2,3,4,5};
        System.out.println("反转之前:");
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
​
        //反转
         /*
        思路:首尾对应位置的元素交换
        (1)确定交换几次
           次数 = 数组.length / 2
        (2)谁和谁交换
        for(int i=0; i<次数; i++){
             int temp = arr[i];
             arr[i] = arr[arr.length-1-i];
             arr[arr.length-1-i] = temp;
        }
         */
        for(int i=0; i<arr.length/2; i++){
            int temp = arr[i];
            arr[i] = arr[arr.length-1-i];
            arr[arr.length-1-i] = temp;
        }
​
        System.out.println("反转之后:");
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }
​
}

public class TestArrayReverse2 {
    public static void main(String[] args) {
        int[] arr = {1,2,3,4,5};
        System.out.println("反转之前:");
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
​
        //反转
        //左右对称位置交换
        for(int left=0,right=arr.length-1; left<right; left++,right--){
            //首  与  尾交换
            int temp = arr[left];
            arr[left] = arr[right];
            arr[right] = temp;
        }
​
        System.out.println("反转之后:");
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }
}

 数组的扩容与缩容

数组的扩容

题目:现有数组 int[] arr = new int[]{1,2,3,4,5}; ,现将数组长度扩容1倍,并将10,20,30三个数据添加到arr数组中,如何操作?

public class ArrTest1 {
    public static void main(String[] args) {
​
        int[] arr = new int[]{1,2,3,4,5};
        int[] newArr = new int[arr.length << 1];
​
        for(int i = 0;i < arr.length;i++){
            newArr[i] = arr[i];
        }
​
        newArr[arr.length] = 10;
        newArr[arr.length + 1] = 20;
        newArr[arr.length + 2] = 30;
​
        arr = newArr;
​
        //遍历arr
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }
}

数组的缩容

题目:现有数组 int[] arr={1,2,3,4,5,6,7}。现需删除数组中索引为4的元素。

public class ArrTest2 {
    public static void main(String[] args) {
​
        int[] arr = {1, 2, 3, 4, 5, 6, 7};
        //删除数组中索引为4的元素
        int delIndex = 4;
        //方案1:
        /*//创建新数组
        int[] newArr = new int[arr.length - 1];
​
        for (int i = 0; i < delIndex; i++) {
            newArr[i] = arr[i];
        }
        for (int i = delIndex + 1; i < arr.length; i++) {
            newArr[i - 1] = arr[i];
        }
​
        arr = newArr;
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }*/
​
        //方案2:
        for (int i = delIndex; i < arr.length - 1; i++) {
            arr[i] = arr[i + 1];
        }
        arr[arr.length - 1] = 0;
​
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }
}

 数组的元素查找

1、顺序查找

顺序查找:挨个查看

要求:对数组元素的顺序没要求

public class TestArrayOrderSearch {
    //查找value第一次在数组中出现的index
    public static void main(String[] args){
        int[] arr = {4,5,6,1,9};
        int value = 1;
        int index = -1;
​
        for(int i=0; i<arr.length; i++){
            if(arr[i] == value){
                index = i;
                break;
            }
        }
​
        if(index==-1){
            System.out.println(value + "不存在");
        }else{
            System.out.println(value + "的下标是" + index);
        }
    }
}

2、二分查找

举例:

实现步骤:

//二分法查找:要求此数组必须是有序的。
int[] arr3 = new int[]{-99,-54,-2,0,2,33,43,256,999};
boolean isFlag = true;
int value = 256;
//int value = 25;
int head = 0;//首索引位置
int end = arr3.length - 1;//尾索引位置
while(head <= end){
    int middle = (head + end) / 2;
    if(arr3[middle] == value){
        System.out.println("找到指定的元素,索引为:" + middle);
        isFlag = false;
        break;
    }else if(arr3[middle] > value){
        end = middle - 1;
    }else{//arr3[middle] < value
        head = middle + 1;
    }
}
​
if(isFlag){
    System.out.println("未找打指定的元素");
}
​

 数组元素排序

 算法概述
  • 定义

    • 排序:假设含有n个记录的序列为{R1,R2,...,Rn},其相应的关键字序列为{K1,K2,...,Kn}。将这些记录重新排序为{Ri1,Ri2,...,Rin},使得相应的关键字值满足条Ki1<=Ki2<=...<=Kin,这样的一种操作称为排序。

    • 通常来说,排序的目的是快速查找。

  • 衡量排序算法的优劣:

    • 时间复杂度:分析关键字的比较次数和记录的移动次数

    • 常见的算法时间复杂度由小到大依次为:Ο(1)<Ο(log2n)<Ο(n)<Ο(nlog2n)<Ο(n2)<Ο(n3)<…<Ο(2n)<Ο(n!)<O(nn)

    • 空间复杂度:分析排序算法中需要多少辅助内存

      一个算法的空间复杂度S(n)定义为该算法所耗费的存储空间,它也是问题规模n的函数。
    • 稳定性:若两个记录A和B的关键字值相等,但排序后A、B的先后次序保持不变,则称这种排序算法是稳定的。

 排序算法概述
  • 排序算法分类:内部排序和外部排序

    • 内部排序:整个排序过程不需要借助于外部存储器(如磁盘等),所有排序操作都在内存中完成。

    • 外部排序:参与排序的数据非常多,数据量非常大,计算机无法把整个排序过程放在内存中完成,必须借助于外部存储器(如磁盘)。外部排序最常见的是多路归并排序。可以认为外部排序是由多次内部排序组成。

  • 十大内部排序算法

数组的排序算法很多,实现方式各不相同,时间复杂度、空间复杂度、稳定性也各不相同:

常见时间复杂度所消耗的时间从小到大排序:

O(1) < O(logn) < O(n) < O(nlogn) < O(n^2) < O(n^3) < O(2^n) < O(n!) < O(n^n)

注意,经常将以2为底n的对数简写成logn。

 冒泡排序(Bubble Sort)

排序思想:

  1. 比较相邻的元素。如果第一个比第二个大(升序),就交换他们两个。

  2. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。

  3. 针对所有的元素重复以上的步骤,除了最后一个。

  4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较为止。

动态演示:排序(冒泡排序,选择排序,插入排序,归并排序,快速排序,计数排序,基数排序) - VisuAlgo

/*
1、冒泡排序(最经典)
思想:每一次比较“相邻(位置相邻)”元素,如果它们不符合目标顺序(例如:从小到大),
     就交换它们,经过多轮比较,最终实现排序。
     (例如:从小到大)   每一轮可以把最大的沉底,或最小的冒顶。
     
过程:arr{6,9,2,9,1}  目标:从小到大
​
第一轮:
    第1次,arr[0]与arr[1],6>9不成立,满足目标要求,不交换
    第2次,arr[1]与arr[2],9>2成立,不满足目标要求,交换arr[1]与arr[2] {6,2,9,9,1}
    第3次,arr[2]与arr[3],9>9不成立,满足目标要求,不交换
    第4次,arr[3]与arr[4],9>1成立,不满足目标要求,交换arr[3]与arr[4] {6,2,9,1,9}
    第一轮所有元素{6,9,2,9,1}已经都参与了比较,结束。
    第一轮的结果:第“一”最大值9沉底(本次是后面的9沉底),即到{6,2,9,1,9}元素的最右边
​
第二轮:
    第1次,arr[0]与arr[1],6>2成立,不满足目标要求,交换arr[0]与arr[1] {2,6,9,1,9}
    第2次,arr[1]与arr[2],6>9不成立,满足目标要求,不交换
    第3次:arr[2]与arr[3],9>1成立,不满足目标要求,交换arr[2]与arr[3] {2,6,1,9,9}
    第二轮未排序的所有元素 {6,2,9,1}已经都参与了比较,结束。
    第二轮的结果:第“二”最大值9沉底(本次是前面的9沉底),即到{2,6,1,9}元素的最右边
第三轮:
    第1次,arr[0]与arr[1],2>6不成立,满足目标要求,不交换
    第2次,arr[1]与arr[2],6>1成立,不满足目标要求,交换arr[1]与arr[2] {2,1,6,9,9}
    第三轮未排序的所有元素{2,6,1}已经都参与了比较,结束。
    第三轮的结果:第三最大值6沉底,即到 {2,1,6}元素的最右边
第四轮:
    第1次,arr[0]与arr[1],2>1成立,不满足目标要求,交换arr[0]与arr[1] {1,2,6,9,9}
    第四轮未排序的所有元素{2,1}已经都参与了比较,结束。
    第四轮的结果:第四最大值2沉底,即到{1,2}元素的最右边
​
*/
public class Test19BubbleSort{
    public static void main(String[] args){
        int[] arr = {6,9,2,9,1};
​
        //目标:从小到大
        //冒泡排序的轮数 = 元素的总个数 - 1
        //轮数是多轮,每一轮比较的次数是多次,需要用到双重循环,即循环嵌套
        //外循环控制 轮数,内循环控制每一轮的比较次数和过程
        for(int i=1; i<arr.length; i++){ //循环次数是arr.length-1次/轮
            /*
            假设arr.length=5
            i=1,第1轮,比较4次
                arr[0]与arr[1]
                arr[1]与arr[2]
                arr[2]与arr[3]
                arr[3]与arr[4]
                
                arr[j]与arr[j+1],int j=0;j<4; j++
                
            i=2,第2轮,比较3次
                arr[0]与arr[1]
                arr[1]与arr[2]
                arr[2]与arr[3]
                
                arr[j]与arr[j+1],int j=0;j<3; j++
                
            i=3,第3轮,比较2次
                arr[0]与arr[1]
                arr[1]与arr[2]
                
                arr[j]与arr[j+1],int j=0;j<2; j++
            i=4,第4轮,比较1次
                arr[0]与arr[1]
            
                arr[j]与arr[j+1],int j=0;j<1; j++
                
                int j=0; j<arr.length-i; j++
            */
            for(int j=0; j<arr.length-i; j++){
                //希望的是arr[j] < arr[j+1]
                if(arr[j] > arr[j+1]){
                    //交换arr[j]与arr[j+1]
                    int temp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = temp;
                }
            }
        }
​
        //完成排序,遍历结果
        for(int i=0; i<arr.length; i++){
            System.out.print(arr[i]+"  ");
        }
    }
}

冒泡排序优化(选讲)

/*
思考:冒泡排序是否可以优化
*/
class Test19BubbleSort2{
    public static void main(String[] args) {
        int[] arr = {1, 3, 5, 7, 9};
​
        //从小到大排序
        for (int i = 0; i < arr.length - 1; i++) {
            boolean flag = true;//假设数组已经是有序的
            for (int j = 0; j < arr.length - 1 - i; j++) {
                //希望的是arr[j] < arr[j+1]
                if (arr[j] > arr[j + 1]) {
                    //交换arr[j]与arr[j+1]
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
​
                    flag = false;//如果元素发生了交换,那么说明数组还没有排好序
                }
            }
            if (flag) {
                break;
            }
        }
​
        //完成排序,遍历结果
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + "  ");
        }
    }
}
快速排序

快速排序(Quick Sort)由图灵奖获得者Tony Hoare发明,被列为20世纪十大算法之一,是迄今为止所有内排序算法中速度最快的一种,快速排序的时间复杂度为O(nlog(n))。

快速排序通常明显比同为O(nlogn)的其他算法更快,因此常被采用,而且快排采用了分治法的思想,所以在很多笔试面试中能经常看到快排的影子。

排序思想:

  1. 从数列中挑出一个元素,称为"基准"(pivot),

  2. 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。

  3. 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

  4. 递归的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了。虽然一直递归下去,但是这个算法总会结束,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。

动态演示:排序(冒泡排序,选择排序,插入排序,归并排序,快速排序,计数排序,基数排序) - VisuAlgo

图示1:

图示2:

第一轮操作:

第二轮操作:

 内部排序性能比较与选择
  • 性能比较

    • 从平均时间而言:快速排序最佳。但在最坏情况下时间性能不如堆排序和归并排序。

    • 从算法简单性看:由于直接选择排序、直接插入排序和冒泡排序的算法比较简单,将其认为是简单算法。对于Shell排序、堆排序、快速排序和归并排序算法,其算法比较复杂,认为是复杂排序。

    • 从稳定性看:直接插入排序、冒泡排序和归并排序时稳定的;而直接选择排序、快速排序、 Shell排序和堆排序是不稳定排序

    • 从待排序的记录数n的大小看,n较小时,宜采用简单排序;而n较大时宜采用改进排序。

  • 选择

    • 若n较小(如n≤50),可采用直接插入或直接选择排序。 当记录规模较小时,直接插入排序较好;否则因为直接选择移动的记录数少于直接插入,应选直接选择排序为宜。

    • 若文件初始状态基本有序(指正序),则应选用直接插入、冒泡或随机的快速排序为宜;

    • 若n较大,则应采用时间复杂度为O(nlgn)的排序方法:快速排序、堆排序或归并排序。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/492129.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Android 性能优化实例分享-内存优化 兼顾效率与性能

背景 项目上线一段时间后,回顾重要页面 保证更好用户体验及生产效率&#xff0c;做了内存优化和下载导出优化&#xff0c;具体效果如最后的一节的表格所示。 下面针对拍摄流程的两个页面 预览页 导出页优化实例进行介绍&#xff1a; 一.拍摄前预览页面优化 预览效果问题 存在…

实时通讯技术实现

实时通讯技术实现 前言 在CS架构中&#xff0c;经常会有实时通信的需求。客户端和服务端建立连接&#xff0c;服务端实时推送数据给客户端。本文介绍几种常见的实现方式&#xff0c;希望能给读者们一点点参考。 实时通讯的主要实现技术 长轮询(Long Polling) WebSocket 服务器发…

搜索(find a way, Pots)

Find a way 思路&#xff1a;这一题看似简单其实不然&#xff0c;有很多特办条件&#xff0c;如果当这个M和Y都在KFC的时候就会导致步数为0 &#xff0c;或者可以这样说&#xff1a;只有两人都能到达才能算入答案。 我们可以使用bfs来写这道题&#xff0c;这不过这道题目不需…

ChatGPT,来一份3·28雷布斯米时捷上市发布会即时发言稿

你新招了一个秘书。上班第一天&#xff0c;你对他说&#xff1a;“3月28号我可能会受邀参加雷老板的米时捷’上市发布会&#xff0c;届时我可能会有十分钟的发言机会&#xff0c;你现在准备一篇演讲稿。” 秘书问你有何指导意见&#xff1f; 你自己都不知说啥子&#xff0c;能…

探秘 RabbitMQ 的设计理念与核心技术要点

目录 一、消息中间件介绍 1.1 消息中间件的作用 二、RabbitMQ 2.1 核心概念 2.2 生产者发送消息过程 2.3 消费者接收消息过程 2.4 RabbitMQ 为何要引入信道(channel) 2.5 消费模式 一、消息中间件介绍 消息队列中间件&#xff08;message queue middleWare, MQ&#xff09;指…

前端发版上线出现白屏问题

目录 路由配置问题资源缓存问题首屏加载过慢 &#xff1a;喂&#xff0c;你的页面白啦&#xff01; 出现上线白屏的问题有很多&#xff0c;如&#xff1a;配置错误、缓存问题、浏览器兼容问题&#xff0c;根据不同情况去解决。 路由配置问题 问题描述&#xff1a; 在vue开发…

ValueError: Cannot load file containing pickled data when allow_pickle=False

问题描述 遇到报错&#xff1a;ValueError: Cannot load file containing pickled data when allow_pickleFalse 解决方案 经过查阅有人说是与numpy的版本有关&#xff0c;但是还是不要轻易改变环境中的版本&#xff0c;不一定哪个地方就会报错。这里放个解决方案&#xff1a;…

【详细讲解yarn的安装和使用】

&#x1f308;个人主页:程序员不想敲代码啊&#x1f308; &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家&#x1f3c6; &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提…

探索MongoDB:发展历程、优势与应用场景

一、MongoDB简介 MongoDB 始于 2007 年&#xff0c;由 Dwight Merriman、Eliot Horowitz 和 Kevin Ryan –&#xff08;DoubleClick 的主理团队&#xff09;共同创立。 DoubleClick 是一家互联网广告公司&#xff08;现隶属于 Google&#xff09;&#xff0c;公司团队开发并利…

数字化转型的密码:传统企业转型路径的深度剖析

引言&#xff1a;数字经济浪潮下的新资产形态 传统行业&#xff0c;如零售、金融、教育等&#xff0c;在如今这场数字化浪潮中&#xff0c;同样需要积极拥抱变革&#xff0c;探索适合自身的转型之路。本文将结合制造业的转型经验&#xff0c;深入探讨传统行…

电脑开机0x0000007B蓝屏怎么办?

电脑开机0x0000007B蓝屏怎么办啊?相信很多用户的电脑都有遇到过蓝屏的问题,最近有用户电脑一开机就蓝屏,并且显示0x0000007B错误代码,原本想通过安全模式进行修复,结果发现安全模式进不去,不知道该怎么解决。这可能与我们的内存或硬盘有关,尝试设置一下硬盘模式,看看是…

嵌入式软件工程师都需要安装哪些软件

文章目录 一、编程软件1.keil2.vscode①Chinese&#xff1a;中文②C/C、C/C Extension Pack③CMake、CMake Tools等代码调试运行的工具④Remote-SSH等&#xff0c;关于远程登录linux服务器的插件 3.Pycharm和Anaconda&#xff0c;用来写python脚本和配置环境&#xff0c;PYQT上…

【Python】搭建 Python 环境

目 录 一.安装 Python二.安装 PyCharm 要想能够进行 Python 开发&#xff0c;就需要搭建好 Python 的环境 需要安装的环境主要是两个部分&#xff1a; 运行环境: Python开发环境: PyCharm 一.安装 Python (1) 找到官方网站 (2) 找到下载页面 选择 “Download for Windows”…

[蓝桥杯 2022 省 A] 求和

[蓝桥杯 2022 省 A] 求和 题目描述 给定 n n n 个整数 a 1 , a 2 , ⋯ , a n a_{1}, a_{2}, \cdots, a_{n} a1​,a2​,⋯,an​, 求它们两两相乘再相加的和&#xff0c;即 S a 1 ⋅ a 2 a 1 ⋅ a 3 ⋯ a 1 ⋅ a n a 2 ⋅ a 3 ⋯ a n − 2 ⋅ a n − 1 a n − 2 ⋅ a…

C语言:动态内存管理(malloc,calloc,realloc,free)

目录 前言 malloc函数 free函数 calloc函数 realloc函数 前言 在这一章节将讲解动态内存分配&#xff0c;它可以在程序的堆区创建一块内存&#xff0c;在这块内存中存什么值就是由自己决定的了 开辟的空间有两个特点&#xff1a; 1. 空间开辟的大小是固定的 2. 数组在…

零基础学习挖掘PHP网站漏洞

教程介绍 本套课程&#xff0c;分为三个阶段&#xff1a;第一阶段&#xff1a;基础篇 学习PHP开发的基础知识&#xff0c;对PHP常见的漏洞进行分析&#xff0c;第二阶段&#xff1a;进阶篇 实战PHP漏洞靶场&#xff0c;了解市面上的PHP主流网站开发技术&#xff0c;并对市面上…

JAVA获取免费天气

JAVA调用天气代码示例 前沿&#xff1a;最近在开发任务中需要获取每日的实时天气和天气预报&#xff0c;要求还是免费的。在网络上搜索了一下免费的API并有了以下思路 免费API网址&#xff1a;https://dev.qweather.com/docs/api/grid-weather/grid-weather-now/ 调用格林天…

工程企业的未来选择:Java版工程项目管理系统平台与数字化管理的融合

在现代化的工程项目管理中&#xff0c;一套功能全面、操作便捷的系统至关重要。本文将介绍一个基于Spring Cloud和Spring Boot技术的Java版工程项目管理系统&#xff0c;结合Vue和ElementUI实现前后端分离。该系统涵盖了项目管理、合同管理、预警管理、竣工管理、质量管理等多个…

基于Colab训练的yolov4-tiny自定义数据集(可用于OpenCV For Unity)

参考资料文档和视频。 1.打开文档,点击【文件】【在云端硬盘中保存一份副本】,即将文档复制到自己云端硬盘。 2.打开该文件,按文中提示进行。 【代码执行程序】【更改运行时类型】修改运行时为GPU(免费的GPU不好用,收费的好用,某宝上几十元就可用一个月) 步骤1) !git…

大数据面试题 —— Kafka

目录 消息队列 / Kafka 的好处消息队列的两种模式什么是 KafkaKafka 优缺点你在哪些场景下会选择 Kafka讲下 Kafka 的整体结构Kafka 工作原理 / 流程Kafka为什么那么快/高效读写的原因 / 实现高吞吐的原理生产者如何提高吞吐量&#xff08;调优&#xff09;kafka 消息数据积压&…