IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 一、排序算法 -> 正文阅读

[数据结构与算法]一、排序算法

排序算法概述

排序算法的用途是对数据集合按照一定规则进行排序,排序算法可以分为两类:
比较类排序:通过比较元素之间的大小,决定相对次序,时间复杂度与数据规模强相关。
非比较类排序:不通过比较元素大小决定次序,时间复杂度和数据规模不强相关,算法复杂度与数据特征有关系。

常用的排序算法如下:

算法时间复杂度最好时间复杂度最差时间复杂度空间复杂度稳定性
冒泡排序 O ( n 2 ) O(n^2) O(n2) O ( n 2 ) O(n^2) O(n2) O ( n 2 ) O(n^2) O(n2) O ( 1 ) O(1) O(1)稳定
快速排序 O ( n l o n g n ) O(nlongn) O(nlongn) O ( n l o n g n ) O(nlongn) O(nlongn) O ( n 2 ) O(n^2) O(n2) O ( n l o n g n ) O(nlongn) O(nlongn)不稳定
选择排序 O ( n 2 ) O(n^2) O(n2) O ( n 2 ) O(n^2) O(n2) O ( n 2 ) O(n^2) O(n2) O ( 1 ) O(1) O(1)不稳定
插入排序 O ( n 2 ) O(n^2) O(n2) O ( n 2 ) O(n^2) O(n2) O ( n ) O(n) O(n) O ( 1 ) O(1) O(1)稳定
归并排序 O ( n l o n g n ) O(nlongn) O(nlongn) O ( n l o n g n ) O(nlongn) O(nlongn) O ( n l o n g n ) O(nlongn) O(nlongn) O ( n l o n g n ) O(nlongn) O(nlongn)稳定
堆排序 O ( n l o n g n ) O(nlongn) O(nlongn) O ( n l o n g n ) O(nlongn) O(nlongn) O ( n l o n g n ) O(nlongn) O(nlongn) O ( 1 ) O(1) O(1)不稳定
桶排序 O ( n + k ) O(n+k) O(n+k) O ( n 2 ) O(n^2) O(n2) O ( n ) O(n) O(n) O ( n + k ) O(n+k) O(n+k)稳定
基数排序 O ( n ? k ) O(n*k) O(n?k) O ( n ? k ) O(n*k) O(n?k) O ( n ? k ) O(n*k) O(n?k) O ( n + k ) O(n+k) O(n+k)稳定
计数排序 O ( n + k ) O(n+k) O(n+k) O ( n + k ) O(n+k) O(n+k) O ( n + k ) O(n+k) O(n+k) O ( n + k ) O(n+k) O(n+k)稳定
希尔排序 O ( n ) O(n) O(n) O ( n 2 ) O(n^2) O(n2) O ( n ) O(n) O(n) O ( 1 ) O(1) O(1)不稳定

常用的排序算法

冒泡排序

从前往后撸一遍,每次把最大的数放在最后,这样最后一个数的位置就确定了。下一次继续从前往后撸到倒数第二个数,确定倒数第二个数。依次进行下去,直到所有的数据都被移动正确的位置。

	private static void bubbleSort(int[] arr) {
		for (int i = arr.length - 1; i > 0; i--) {
			for (int j = 0; j < i; j++) {
				if(arr[j]>arr[j+1]) {
					swap(arr, j, j+1);
				}
			}
		}
	}
	public static void swap(int[] arr, int i, int j) {
		int tmp = arr[i];
		arr[i] = arr[j];
		arr[j] = tmp;
	}

举例:5、1、9、8、7
第一次循环结果:1、5、8、7、9
第二次循环结果:1、5、7、8、9
第三次循环结果:1、5、7、8、9
第四次循环结果:1、5、7、8、9
第五次循环结果:1、5、7、8、9

快速排序

快速排实际上是利用递归的思想,将数组分成大小两个部分,在大、小两个区间保证有序,进而保证整体有序。

	// 保证数组arr l-->r区间有序
	public static void quickSort(int[] arr, int l, int r) {
		if (l < r) {
		    // 利用随机数进行优化(下把为r的数为最小值),
			swap(arr, l + (int) (Math.random() * (r - l + 1)), r);
			int[] p = partition(arr, l, r);
			quickSort(arr, l, p[0] - 1);
			quickSort(arr, p[1] + 1, r);
		}
	}
    // 将arr数组l-->r区间分为大小两个部分(以下标r作为基准),返回两个元素的数组优化元素相等时的排序
	public static int[] partition(int[] arr, int l, int r) {
		int less = l - 1;
		int more = r;
		while (l < more) {
			if (arr[l] < arr[r]) {
				swap(arr, ++less, l++);
			} else if (arr[l] > arr[r]) {
				swap(arr, --more, l);
			} else {
				l++;
			}
		}
		// 大的数与最后一个素交换
		swap(arr, more, r);
		return new int[] { less + 1, more };
	}
	public static void swap(int[] arr, int i, int j) {
		int tmp = arr[i];
		arr[i] = arr[j];
		arr[j] = tmp;
	}

举例:5、1、9、8、7(暂时不考虑随机数)
第一次排序:1、5、8、7、9(用5将数据分为两个区域{1}、{8,7,9})
第二次排序:1、5、7、8、9(小于5的区域{1}不需要排序,大于5的区域{8,7,9}用第一个数8作为基准继续排序)

选择排序

选择排序,从头到尾依次遍历,找到最小的值,放在前面,每次确定一个数字的位置。

	private static void selectSort(int[] arr) {
		for (int i = 0; i < arr.length; i++) {
			// 记录i-->length-1最小值的下标
			int index = i;
			for(int j = i + 1; j < arr.length; j++) {
				if (arr[index] > arr[j]) {
					index = j;
				}
			}
			// 最小值与i交换
			swap(arr, index, i);
		}
	}
	public static void swap(int[] arr, int i, int j) {
		int tmp = arr[i];
		arr[i] = arr[j];
		arr[j] = tmp;
	}

举例:5、1、9、8、7
第一次排序:1、5、9、8、7
第二次排序:1、5、9、8、7
第三次排序:1、5、7、8、9
第四次排序:1、5、7、8、9
第五次排序:1、5、7、8、9

插入排序

已下标 i i i的数为基准,假设 0 ? > i ? 1 0->i-1 0?>i?1有序,将下标 i i i的数插入到合适的位置保存 0 ? > i 0->i 0?>i有序。遍历一轮保证全部有序。

	private static void insertSort(int[] arr) {
		for (int i = 1; i < arr.length; i++) {
			for(int j = i - 1; j >= 0 && arr[j] > arr[j + 1]; j--) {
				swap(arr, j, j + 1);
			}
		}
	}
	public static void swap(int[] arr, int i, int j) {
		int tmp = arr[i];
		arr[i] = arr[j];
		arr[j] = tmp;
	}

举例:5、1、9、8、7
第一次排序:1、5、9、8、7
第二次排序:1、5、9、8、7
第三次排序:1、5、8、9、7
第四次排序:1、5、7、8、9

归并排序

归并排序采用分治的思想,将数组分为两个区间,对区间内进行排序,然后使用一个辅助数组对两个区间进行合并。

	public static void mergeSort(int[] arr, int l, int r) {
		if (l == r) {
			return;
		}
		int mid = l + ((r - l) >> 1);
		mergeSort(arr, l, mid);
		mergeSort(arr, mid + 1, r);
		merge(arr, l, mid, r);
	}

	public static void merge(int[] arr, int l, int m, int r) {
		int[] help = new int[r - l + 1];
		int i = 0;
		int p1 = l;
		int p2 = m + 1;
		while (p1 <= m && p2 <= r) {
			help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
		}
		while (p1 <= m) {
			help[i++] = arr[p1++];
		}
		while (p2 <= r) {
			help[i++] = arr[p2++];
		}
		for (i = 0; i < help.length; i++) {
			arr[l + i] = help[i];
		}
	}

举例:5、1、9、8、7
第一次排序:1、5、9、7、8
第二次排序:1、5、7、8、9

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-08-18 12:56:50  更:2021-08-18 12:57:07 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 21:27:59-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码