八种排序算法总结
作者:互联网
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
八种排序算法
前言
自学了几种常见的排序算法,做个简单的总结
一、排序算法(Sort Algorithm)的分类
二、八种排序
1.冒泡排序
代码如下(示例):
// 将前面额冒泡排序算法,封装成一个方法 ,从小到大排序
public static void bubbleSort(int[] arr) {
int temp;
Boolean flag = false; //标识变量,表示是否进行过交换,
//一趟下来,如果没有交换过,说明数组已经有序,则不需继续遍历
for(int i = 0;i < arr.length;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 {
//交换过,要重新设置为false,为下一趟做准备
flag = false;
}
}
}
2.选择排序
2.1思路分析
- 选择排序一共进行:数组大小-1轮
- 每一轮选出一个最小的数排在第一位
代码如下(示例):
private static void Select(int[] arr){
for(int i = 0;i<arr.length-1;i++){
int minIndex = i;//记录最小值下标
int min = arr[i];//记录最小值
for(int j = i;j < arr.length-1;j++){
if (arr[j] < min) {//找到一个数比当前数小,就记录下来
min = arr[j];
minIndex = j;
}
}
if(minIndex != i){//找到一个最小的值,则和最前面的数进行交换
arr[minIndex] = arr[i];
arr[i] = min;
}
}
}
3.插入排序(Insertion Sorting)
3.1 思路
插入排序的基本思想是:把 n 个待排序的元素看成为一个有序表和一个无序表,开始时有 序表中只包含一个元素,无序表中包含有 n-1 个元素,排序过程中每次从无序表中取出第一个元素,把它的排序码依次与有序表元素的排序码进行比较,将它插入到有序表中的适当位置,使之成为新的有序表。
3.2 代码
public static void insert(int[] arr){
int insertVal = 0;
int insertIndex = 0;
for(int i = 1;i < arr.length;i++){
insertVal = arr[i];//记录插入的值
insertIndex = i -1;//记录插入数的前一个数
while(insertIndex >= 0 && (insertVal < arr[insertIndex])){
//比较当前插入值和当前值,找出最小的位置插入
arr[insertIndex+1] = arr[insertIndex];//将数后移,空出插入的位置
insertIndex--;//往前面找
}
if(insertIndex+1 != i){//判断指针是否有动
arr[insertIndex + 1] = insertVal;//如果有动,就将当前位置改为插入值
//为什么insertIndex 要加1 : 因为前一步出来的时候insertIndex 是多减了一下
}
}
}
4.希尔排序
4.1 基本思想
希尔排序 是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含 的关键词越来越多,当增量减至 1 时,整个文件恰被分成一组,算法便终止
4.2 思路图
int insertVal;//记录插入值
int insertIndex;//记录当前要插入值对应的下标
for(int gap = arr.length/2;gap > 0;gap /= 2){
//将整个数据分组,分为length / 2组,并不断缩小增量 gap /= 2
for(int i = gap;i < arr.length;i++){
//每一次分组都用插入排序
//记录每一次插入排序的初始位置,从后面开始
insertVal = arr[i]; //插入值初始化
insertIndex = i; //当前要插入值的下标
while(insertIndex - gap >= 0 && (insertVal < arr[insertIndex-gap] )){
//当前要插入的前一个必须有值,否则就不会进入
//并且前一个值大于要插入的值,才能进入
arr[insertIndex] = arr[insertIndex-gap];//将前一个值移到当前位置
insertIndex-=gap;//然后位置向前移动一步
}
if(insertIndex != i){//如果当前值没有动,说明当前值是已经小的了,不用插入了
arr[insertIndex] = insertVal;//否则,就将插入值,插入到当前位置
}
}
}
5. 快速排序(Quicksort)
5.1思路
5.2 代码
public static void QuickSort(int[] arr, int left, int right){
int l = left;
int r = right;
int pivot = arr[(left+right)/2];//记录中间值
int temp = 0;//临时变量,用于交换
while (l < r ){
while(arr[l] < pivot){//在左边找到一个比pivot大的数的下标
l++;
}
while(arr[r] > pivot){//在右边找到一个比pivot小的数的下标
r--;
}
if (l >= r) {
break;
}
//交换左右两个值
temp = arr[l];
arr[l] = arr[r];
arr[r] = temp;
if(arr[l] == pivot){
r--;
}
if(arr[r] == pivot){
l++;
}
if(l == r){
l++;
r--;
}
if(left < r){
QuickSort(arr,left,r);
}
if(right > l){
QuickSort(arr, l, right);
}
}
}
6. 归并排序
6.1 思路
6.2 代码
//分
public static void mergeSort(int[] arr, int left, int right, int[] temp) {
if(left < right){
int mid = (left + right)/2;
mergeSort(arr,left,mid,temp);
mergeSort(arr,mid+1,right,temp);
merge(arr,left,mid,right,temp);
}
}
//治
public static void merge(int[] arr, int left, int mid, int right, int[] temp) {
int i = left;//左边有序序列的初始索引
int j = mid + 1;//右边有序序列的初始索引
int t = 0;//指向temp数组的当前索引
while(i <= mid && j <= right){//继续
//如果左边的有序序列的当前元素,小于
if(arr[i] <= arr[j]){
temp[t] = arr[i];
t++;
i++;
} else {
temp[t] = arr[j];
t++;
j++;
}
}
while(i <= mid){
temp[t++] = arr[i++];
}
while(j <= right){
temp[t++] = arr[j++];
}
t = 0;
int tempLeft = left;
while(tempLeft <= right){
arr[tempLeft++] = temp[t++];
}
}
7.基数排序
7.1 思路
将所有待比较数值统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。 这样从最低位排序一直到最高位排序完成以后, 数列就变成一个有序序列
7.2 代码
public static void radixSort(int arr[]){
//得到数组中最大的数的位数
int max = arr[0];
for (int i = 0; i < arr.length; i++) {
if(arr[i] > max ){
max = arr[i];
}
}
//得到最大的数是多少位
int maxLength = (max + "").length();
//定义一个二维数组,表示 10 个桶, 每个桶就是一个一维数组
// 说明
// 1. 二维数组包含 10 个一维数组
// 2. 为了防止在放入数的时候,数据溢出,则每个一维数组(桶),大小定为 arr.length
// 3. 名明确,基数排序是使用空间换时间的经典算法
int[][] bucket = new int[10][arr.length];
//为了记录每个桶中,实际存放了多少个数据,我们定义一个一维数组来记录各个桶的每次放入的数据个数
//比如:bucketElementCounts[0] , 记录的就是 bucket[0] 桶的放入数据个数
int[] bucketElementCounts = new int[10];
for(int i = 0,n = 1; i < maxLength;i++,n *= 10){
//n是用于的到对应数的位数
for (int j = 0; j < arr.length; j++) {
int digitOfElement = arr[j]/n % 10;
bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j];
bucketElementCounts[digitOfElement]++;
}
//按照这个桶的顺序(一维数组的下标依次取出数据,放入原来数组)
int index = 0;
//遍历每一桶,并将桶中是数据,放入到原数组
for (int k = 0; k < bucketElementCounts.length; k++) {
if (bucketElementCounts[k] != 0){
for (int l = 0; l < bucketElementCounts[k]; l++) {
arr[index++] = bucket[k][l];
}
}
//第 i+1 轮处理后,需要将每个 bucketElementCounts[k] = 0 !!!!
bucketElementCounts[k] = 0;
}
}
}
8.堆排序
跟基数排序原理差不多,这里就省略了
总结
常见算法的比较
总结
几种排序算法,大多数都是从尚硅谷学习,大家有兴趣可以去看视频学习,在b站就可以找到相视频
标签:arr,temp,int,insertIndex,八种,++,算法,排序 来源: https://blog.csdn.net/m0_52963553/article/details/120126440