【数据结构和算法】排序算法(一)

冒泡排序【重要】

时间复杂度O(n^2) 两次for循环

  • 遍历length-1趟数组,然后每一趟再遍历length-1-i次数组(从0开始),每次找到最大值与[length-i]交换

img

public static void bubbleSort(int[] arr) {
    
    
		int temp = 0; // 临时变量
		boolean flag = false; // 标识变量,表示是否进行过交换 这里是为了优化
		for (int i = 0; i < arr.length - 1; i++) {
    
    
			for (int j = 0; j < arr.length - 1 - i; j++) {
    
    
				// 如果前面的数比后面的数大,则交换
				if (arr[j] > arr[j + 1]) {
    
    
					flag = true;
					temp = arr[j];
					arr[j] = arr[j + 1];
					arr[j + 1] = temp;
				}
			}
			if (!flag) {
    
     // 在一趟排序中,一次交换都没有发生过 说明已经有序了就不用再遍历了
				break;
			} else {
    
    
				flag = false; // 重置flag!!!, 进行下次判断
			}
		}
	}

快速排序【重要】

时间复杂度 O(nlogn) 类似于二分法 每次减半,相当于兔生兔

  • 对冒泡的一种改进,每趟排序将数组分为两个部分 。相当于树,左小右大,然后再将这两部分递归

在这里插入图片描述

public static void quickSort(int[] arr,int left, int right) {
    
    
    int l = left; //左下标
    int r = right; //右下标
    //pivot 中轴值
    int pivot = arr[(left + right) / 2];
    int temp = 0; //临时变量,作为交换时使用
    //while循环的目的是让比pivot 值小放到左边
    //比pivot 值大放到右边
    while( l < r) {
    
     
        //在pivot的左边一直找,找到大于等于pivot值,才退出
        while( arr[l] < pivot) {
    
    
            l += 1;
        }
        //在pivot的右边一直找,找到小于等于pivot值,才退出
        while(arr[r] > pivot) {
    
    
            r -= 1;
        }
        //如果l >= r说明pivot 的左右两的值,已经按照左边全部是
        //小于等于pivot值,右边全部是大于等于pivot值
        if( l >= r) {
    
    
            break;
        }
        //交换
        temp = arr[l];
        arr[l] = arr[r];
        arr[r] = temp;
        //如果交换完后,发现这个arr[l] == pivot值 相等 r--, 前移
        if(arr[l] == pivot) {
    
    
            r -= 1;
        }
        //如果交换完后,发现这个arr[r] == pivot值 相等 l++, 后移
        if(arr[r] == pivot) {
    
    
            l += 1;
        }
    }
    // 如果 l == r, 必须l++, r--, 否则为出现栈溢出
    if (l == r) {
    
    
        l += 1;
        r -= 1;
    }
    //向左递归
    if(left < r) {
    
    
        quickSort(arr, left, r);
    }
    //向右递归
    if(right > l) {
    
    
        quickSort(arr, l, right);
    }
}

选择排序

  • 和冒泡性质一样,遍历length-1趟,每趟遍历length-1-i次数组(即从i+1开始遍历)找到最小值与arr[i]交换,时间复杂度O(n^2)

在这里插入图片描述

//选择排序
public static void selectSort(int[] arr) {
    
    
    for (int i = 0; i < arr.length - 1; i++) {
    
    
        int minIndex = i;
        int min = arr[i];
        for (int j = i + 1; j < arr.length; j++) {
    
    
            if (min > arr[j]) {
    
     // 说明假定的最小值,并不是最小
                min = arr[j]; // 重置min
                minIndex = j; // 重置minIndex
            }
        }
        // 将最小值,放在arr[0], 即交换
        if (minIndex != i) {
    
    
            arr[minIndex] = arr[i];
            arr[i] = min;
        }
    }
}

插入排序

  • 即从第二个开始遍历length次依次往左插入,将arr[i]循环与前面数arr[i-1]相比,不满足则将arr[i-1]后移,然后再与arr[i-1-1]相比… 时间复杂度O(n^2)

在这里插入图片描述

//插入排序
public static void insertSort(int[] arr) {
    
    
    int insertVal = 0;
    int insertIndex = 0;
    //使用for循环来把代码简化
    for(int i = 1; i < arr.length; i++) {
    
    
        //定义待插入的数
        insertVal = arr[i];
        insertIndex = i - 1; // 即arr[1]的前面这个数的下标

        // 给insertVal 找到插入的位置
        // 说明
        // 1. insertIndex >= 0 保证在给insertVal 找插入位置,不越界
        // 2. insertVal < arr[insertIndex] 待插入的数,还没有找到插入位置
        // 3. 就需要将 arr[insertIndex] 后移
        while (insertIndex >= 0 && insertVal < arr[insertIndex]) {
    
    
            arr[insertIndex + 1] = arr[insertIndex];// arr[insertIndex]
            insertIndex--;
        }
        // 当退出while循环时,说明插入的位置找到, insertIndex + 1
        // 举例:理解不了,我们一会 debug
        //这里我们判断是否需要赋值
        if(insertIndex + 1 != i) {
    
    
            arr[insertIndex + 1] = insertVal;
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_51998352/article/details/121005043