排序算法总结

排序算法总结

选择排序

public static void selectSort(int[] arr) {
	if (arr == null || arr.length < 2) {
		return;
	}
	// 0 ~ N-1  找到最小值,在哪,放到0位置上
	// 1 ~ n-1  找到最小值,在哪,放到1 位置上
	// 2 ~ n-1  找到最小值,在哪,放到2 位置上
	for (int i = 0; i < arr.length - 1; i++) {
		int minIndex = i;
		for (int j = i + 1; j < arr.length; j++) { // i ~ N-1 上找最小值的下标 
			minIndex = arr[j] < arr[minIndex] ? j : minIndex;
		}
		int tmp = arr[i];
		arr[i] = arr[minIndex];
		arr[minIndex] = tmp;
	}
}

冒泡排序

冒泡排序的基本思想是通过重复地交换相邻的未按次序排列的元素,每一轮将未排序部分中最大的元素向右移动。

public static void bubbleSort(int[] arr){
	if (arr == null || arr.length < 2) {
        return;
    }
    for (int end = arr.length - 1; end >= 0; end--) {
		for (int i = 0; i < end; i++) {
			if (arr[i + 1] < arr[i]) {
				int temp = arr[i];
				arr[i] = arr[i + 1];
				arr[i + 1] = temp;
			}
		}
	}
}

插入排序

插入排序的基本思想是将一个元素插入到已经有序的部分中,直到所有元素都有序为止。

public static void insertSort(int[] arr) {
	if (arr == null || arr.length < 2) {
		return;
	}
	for (int i = 1; i < arr.length; i++) {
		int tmp = arr[i];
		int j = i - 1;
		while (j >= 0 && arr[j] > tmp) {
			arr[j + 1] = arr[j];
			j--;
		}
		arr[j + 1] = tmp;
	}
}

归并排序

public static void mergeSort(int[] arr) {
    if (arr == null || arr.length < 2) {
        return;
    }
    process(arr, 0, arr.length);
}

public static void process(int[] arr, int L, int R){
    if (L >= R) {
        return;
    }
    //int mid = L + (R - L) / 2;
    //取中点
    int mid = L + ((R - L) >> 1);
    process(arr, L, mid);
    process(arr, mid + 1, R);
    merge(arr, L, mid, R);
}

public static void merge(int[] arr, int L, int mid, int R) {
    int[] temp = new int[R - L + 1];
    int i = L, j = mid + 1, k = 0;
    while (i <= mid && j <= R) {
        temp[k++] = arr[i] <= arr[j] ? arr[i++] : arr[j++];
    }
    while (i <= mid) {
        temp[k++] = arr[i++];
    }
    while (j <= R) {
        temp[k++] = arr[j++];
    }
    for (int m = 0; m < temp.length; m++) {
        arr[L + m] = temp[m];
    }
}

随机快速排序

递归实现

public static void QuickSort1(int[] arr) {
    if (arr == null || arr.length < 2) return;
    process(arr, 0, arr.length - 1);
}

public static void process(int[] arr, int L, int R) {
    if (L >= R) return;
    swap(arr, (int) Math.random() * (R - L + 1), R);
    int[] equlArea = netherlandsFlag(arr, L, R);
    process(arr, L, equlArea[0] - 1);
    process(arr, equlArea[1] + 1, R);
}

//返回等于 R 的区间下标
public static int[] netherlandsFlag(int[] arr, int L, int R) {
    if (L > R) return new int[]{-1, -1};
    if (L == R) return new int[]{L, L};
    int less = L - 1;
    int more = R;
    int index = L;
    while (index < more) {
        if (arr[index] < arr[R]) {
            swap(arr, index++, ++less);
        } else if (arr[index] > arr[R]) {
            swap(arr, index, --more);
        } else {
            index++;
        }
    }
    swap(arr, more, R);
    return new int[]{less + 1, more};
}

public static void swap(int[] arr, int i, int j) {
    int temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}

非递归- 栈实现

public static class Op{
    public int l;
    public int r;
    public Op(int left, int right) {
        this.l = left;
        this.r = right;
    }
}
public static void QuickSort2(int[] arr) {
    if (arr == null || arr.length < 2) return;
    int N = arr.length;
    swap(arr, N - 1, (int) (Math.random() * N));
    int[] equalArea = netherlandsFlag(arr, 0, N - 1);
    int el =equalArea[0];
    int er = equalArea[1];
    Stack<Op> stack = new Stack<>();
    stack.push(new Op(0, el - 1));
    stack.push(new Op(er + 1, N - 1));
    while (!stack.isEmpty()) {
        Op op = stack.pop();
        if (op.l < op.r) {
            swap(arr, op.l + (int) (Math.random() * (op.r - op.l + 1)), op.r);
            equalArea = netherlandsFlag(arr, op.l, op.r);
            el = equalArea[0];
            er = equalArea[1];
            stack.push(new Op(op.l, el - 1));
            stack.push(new Op(er + 1, op.r));
        }
    }
}
//返回等于 R 的区间下标
public static int[] netherlandsFlag(int[] arr, int L, int R) {
    if (L > R) return new int[]{-1, -1};
    if (L == R) return new int[]{L, L};
    int less = L - 1;
    int more = R;
    int index = L;
    while (index < more) {
        if (arr[index] < arr[R]) {
            swap(arr, index++, ++less);
        } else if (arr[index] > arr[R]) {
            swap(arr, index, --more);
        } else {
            index++;
        }
    }
    swap(arr, more, R);
    return new int[]{less + 1, more};
}

public static void swap(int[] arr, int i, int j) {
    int temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}

非递归- 队列实现

public static void QuickSort3(int[] arr){
    if (arr == null || arr.length < 2) return;
    int N = arr.length;
    swap(arr, N - 1, (int) (Math.random() * N));
    int[] equalArea = netherlandsFlag(arr, 0, N - 1);
    int el = equalArea[0];
    int er = equalArea[1];
    Queue<Op> queue = new LinkedList<Op>();
    queue.offer(new Op(0, el - 1));
    queue.offer(new Op(er + 1, N - 1));
    while (!queue.isEmpty()) {
        Op op = queue.poll();
        if (op.l < op.r) {
            swap(arr, op.l + (int) (Math.random() * (op.r - op.l + 1)), op.r);
            equalArea = netherlandsFlag(arr, op.l, op.r);
            el = equalArea[0];
            er = equalArea[1];
            queue.offer(new Op(op.l, el - 1));
            queue.offer(new Op(er + 1, op.r));
        }
    }
}
public static class Op{
    public int l;
    public int r;
    public Op(int left, int right) {
        this.l = left;
        this.r = right;
    }
}
//返回等于 R 的区间下标
public static int[] netherlandsFlag(int[] arr, int L, int R) {
    if (L > R) return new int[]{-1, -1};
    if (L == R) return new int[]{L, L};
    int less = L - 1;
    int more = R;
    int index = L;
    while (index < more) {
        if (arr[index] < arr[R]) {
            swap(arr, index++, ++less);
        } else if (arr[index] > arr[R]) {
            swap(arr, index, --more);
        } else {
            index++;
        }
    }
    swap(arr, more, R);
    return new int[]{less + 1, more};
}

public static void swap(int[] arr, int i, int j) {
    int temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}

堆排序

大根堆实现堆排序

public static void heapSort(int[] arr) {
    if (arr == null || arr.length < 2) return;
	int N = arr.length;
    // 建堆(构造大根堆)
	for (int i = N / 2 - 1; i >= 0; i--) {
		heapify(arr, N, i);
	}
    // 堆排序(依次交换堆顶和最后一个元素,并进行堆调整)
	for (int i = N - 1; i >= 0; i--) {
		swap(arr, 0, i);
		heapify(arr, 0, i);
	}
}
public static void heapify(int[] arr, int N, int i) {
    int left = 2 * i + 1;
    int right = 2 * i + 2;
    int largest = i; // 假设当前节点的值最大
    // 如果左子节点的值大于当前节点的值,则更新最大节点
    if (left < N && arr[left] > arr[largest]) {
        largest = left;
    }
    // 如果右子节点的值大于当前节点的值,则更新最大节点
    if (right < N && arr[right] > arr[largest]) {
        largest = right;
    }
    // 如果最大节点不是当前节点,则进行交换,并对交换后的节点进行堆调整
    if (largest!= i) {
        swap(arr, i, largest);
        heapify(arr, N, largest);
    }
}

桶排序

计数排序

public static void countSort(int[] arr) {
    if (arr == null || arr.length < 2) return;
    int max = Integer.MIN_VALUE;
    for (int i = 0; i < arr.length; i++) {
        max = Math.max(max, arr[i]);
    }
    //按最大值创建辅助数组
    int[] bucket = new int[max + 1];
    //按值进桶记录
    for (int i = 0; i < arr.length; i++) {
        bucket[arr[i]]++;
    }
    int i = 0;
    //出桶,bucket是几就说明这个数出现了几次
    for (int j = 0; j < bucket.length; j++) {
        while (bucket[j]-- >0) {
            arr[i] = j;
        }
    }
}

基数排序

public static void radixSort(int[] arr) {
    if (arr == null || arr.length < 2) return;
    radixSort(arr, 0, arr.length - 1, maxbits(arr));
}
//返回数组中最大的数是几位数
public static int maxbits(int[] arr) {
    int max = Integer.MIN_VALUE;
    for (int i = 0; i < arr.length; i++) {
        max = Math.max(max, arr[i]);
    }
    int res = 0;
    while (max != 0) {
        res++;
        max /= 10;
    }
    return res;
}

public static void radixSort(int[] arr, int L, int R, int maxbit) {
    final int redix = 10;
    int i = 0, j = 0;
    int[] help = new int[R - L + 1];
    for (int x = 1; x <= maxbit; x++) {
        //创建辅助数组
        int[] count = new int[redix];
//进桶,根据位上的数在辅助数组中记录
        for (i = L; i <= R; i++) {
            j = getDigit(arr[i], x);
            count[j]++;
        }
//求前缀和
        for (i = 1; i < redix; i++) {
            count[i] += count[i - 1];
        }
        //按顺序出桶,
        for (i = L; i <= R; i++) {
            j = getDigit(arr[i], x);
            help[count[j] - 1] = arr[i];
            count[j]--;
        }
        //给原数组赋值
        for (i = L; i <= R; i++) {
            arr[i] = help[i - L];
        }
    }
}
//返回数x在d位上是多少
public static int getDigit(int x, int d) {
    return (x / (int) Math.pow(10, d - 1)) % 10;
}
算法时间复杂度额外空间复杂度稳定性
选择排序O(N^2)O(1)
冒泡排序O(N^2)O(1)
插入排序O(N^2)O(1)
归并排序O(N*logN)O(N)
随机排序O(N*logN)O(logN)
堆排序O(N*logN)O(1)
计数排序O(N)O(N)
基数排序O(N)O(N)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值