常见排序方式:冒泡、选择、插入、希尔、快速、归并,基数

(以下代码演示默认从小到大排)

冒泡排序 : 两两比较,交换

1.优点:比较简单,空间复杂度较低,是稳定的;                 

 2.缺点:时间复杂度太高,效率慢;

冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越大的元素会经由交换慢慢“浮”到数列的顶端。

package com.yc.test;

public class bubbleSort {
	public static void main(String[] args) {
		int[] arr = new int[]{8, 2, 5, -332, 15, 78};
		Bubbling(arr);	
		//输出arr数组
		for( int a: arr) {
			System.out.print(a + "  ");
		}
	}
	//冒泡排序:让索引在j位置的 与 j + 1的依次进行比较,如果比他小,则交换位置 交换 length-1次
	public static void Bubbling(int[] arr) {
		//冒泡顺序,只要排length - 1次 因为其他的都排好了,最后一位也就不用排了
		for(int i = 0; i < arr.length - 1; i ++){
			//优化步骤  当没进行arr.length次数就排完了,那就不用排了
			boolean flag = true;
			//冒泡步骤  让索引在j位置的 与 j + 1的进行比较,如果比他小,则交换位置
			for(int j = 0; j < arr.length - 1 - i; j ++) {
				if(arr[j] > arr[j + 1]) {//交换位置  进到这里面来 就说明还有要进行交换的两个数字
					flag = false;
					int temp = arr[j];
					arr[j]= arr[j + 1];
					arr[j + 1] = temp;
				}
			}
			//如果 flag 为true 说明,没进行数字交换,所以已经排完了,所以直接结束
			if(flag) {
				break;
			}
		}
	}
}

 选择排序:从前往后,拿出一个与后面的比较,选出最小的(或大的)依次放好

 缺点:比较次数多(也就是数组长度 - 1);不稳定。

选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。 选择排序是不稳定的排序方法。

package com.yc.test;
public class selectSort {
	public static void main(String[] args) {
		int[] arr = new int[]{8, 2, 5, -332, 15, 78};
		SelectSort(arr);	
		//输出arr数组
		for( int a: arr) {
			System.out.print(a + "  ");
		}
	}
	//选择排序:从索引第一位开始,依次与后面的数进行比较,选出最小的放在第一位,第二次排序选择第二小的放在第二位,以此类推
	public static void SelectSort(int[] arr) {
		for(int i = 0; i < arr.length - 1; i ++) {//排序的次数,是数组长度减一,因为选到倒数第二位(第二大)的时候,已经排完了
			int min = arr[i]; //拿出一个数,与之后的所有数进行比较,如果有比他更小的,min就等于那个更小的
			int minindex = i; //这是这个数的索引,待会用于交换位置
			//进行比较,循环i之后的数字,j就是后面每个数字的索引
			for (int j = i + 1; j < arr.length; j ++) {
				if(min > arr[j]) {//如果当前选中的这个数,比下一个数要大,那就说明下一个数比他小:选中他!
					min = arr[j];//把最小数换成比他小的那个
					minindex = j;//最小数的索引也换成这个
				}
			}
			//判断: 如果min发生改变,说明需要交换位置
			if (i != minindex) {
				arr[minindex] = arr[i];  //最小数的原位置放索引为i的数字
				arr[i] = min;    //遍历的第i个就放i后面的所有数中最小的那个
			}
		}
	}
}

 插入排序:每步遍历一个值,按值的大小插入前面已经排序的文件中适当位置上,直到全部插入完为止。(从前往后,拿出一个数与他前面的数进行比较,如果比他大,就继续往前,直到他前面那个数不比他大,就插在不比他大的那个数后面)

优点:稳定,快

缺点:比较次数不一定,比较次数越少,插入点后的数据移动越多,特别是当数据总量庞大的时候

package com.yc.test;
public class insertSort {
	public static void main(String[] args) {
		int[] arr = new int[]{8, 2, 5, -332, 15, 78};
		insertSort(arr);	
		//输出arr数组
		for( int a: arr) {
			System.out.print(a + "  ");
		}
	}
	/**
	 * 插入排序:从索引第二位开始,把它与之前的数字进行比较,如果比他大,就插到他前面,直到他前面那个数字不比他大
	 *因为前面的都已经排好序了,所以中间的只要往前走,找到比他大的,插到他前面就行了。
	 *前面没有比他大的,那就说明到他这,他都是最小的,会插到最前面。这个数字插完之后,继续下一个数字的比较和插入
	 */
	public static void insertSort(int[] arr) {
		//循环遍历数组中每个数字,从第二个开始,因为第一个前面没有数字,没法比
		for( int i = 1; i < arr.length; i ++) {  //i为索引,从前往后依次遍历
			int insertIndex = i; //这是要比较的那个数的索引
			int insertValue = arr[i];//这是要与别人比较的那个数
			/**往前走,索引减一。  直到insertValue(要比较的数)的索引为0,已经到最前面了
			 * 或者insertValue(要比较的数)不小于他前面那个数,就停止循环
			 */
			while( insertIndex - 1 >= 0 && insertValue < arr[insertIndex - 1]) {
				arr[insertIndex] = arr[insertIndex - 1];//他原来位置就放前一个比他大的数
				insertIndex--; 
			}
			arr[insertIndex] = insertValue;//把这个数放到找到的索引位置
		}
	}
}

希尔排序: 高级点的插入排序,每次多往前走几步比较插入,先粗略比较,再细致比较

(注:希尔是个人,他提出希尔排序)

优点:快,数据移动少

缺点:不稳定,步长的取值是多少也很难判断

package com.yc.test;
public class shellSort {
	public static void main(String[] args) {
		int[] arr = new int[]{8, 2, 5, -332, 15, 78};
		insertSort(arr);	
		//输出arr数组
		for( int a: arr) {
			System.out.print(a + "  ");
		}
	}
	/**
	 * 插入排序:就是高级点的插入排序,每次多往前走几步比较,闲粗略比较,再细致比较
	 */
	public static void insertSort(int[] arr) {
		//gap 为步长,意思就是不与前一位的比较,与前gap位的比较,比较完了,再缩短步长,再进行比较。可以加快比较速度
		for (int gap = arr.length / 2; gap > 0; gap /= 2) {//缩短步长
			//循环遍历数组中每个数字,从第二个开始,因为第一个前面没有数字,没法比
			for( int i = gap; i < arr.length; i ++) {  //i为索引,从前往后依次遍历
				//插入式 间隔为gap的插入排序
				int insertIndex = i; //这是要比较的那个数的索引
				int insertValue = arr[i];//这是要与别人比较的那个数
				/**往前走,索引减gap。  如果insertValue(要比较的数)的索引为0,已经到最前面了
				 * 或者insertValue(要比较的数)不小于他前面那个数,就停止循环
				 */
				while( insertIndex - gap >= 0 && insertValue < arr[insertIndex - gap]) {
					arr[insertIndex] = arr[insertIndex - gap];//他原来位置就放前一个比他大的数
					insertIndex -= gap; 
				}
				arr[insertIndex] = insertValue;//把这个数放到找到的索引位置
			}
		}
	}
}

 快速排序:通过一躺排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一不部分的所有数据都要小,然后再按次方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。快速排序使用分治法策略来把一个序列分为两个子序列。

优点 :目前已知最快的排序方法,数据移动少;

缺点:不稳定,代码有点难理解,建议多看看视频

package com.yc.test;
public class QuickSort {
	public static void main(String[] args) {
		int[] arr = new int[]{8, 2, 5, -332, 15, 78};
		quickSort(arr, 0, arr.length - 1);	
		//输出arr数组
		for( int a: arr) {
			System.out.print(a + "  ");
		}
	}
	 //快速排序:选一个中心数字(一般是开头左边第一个),比她大的放右边,比他小的放左边,然后再对左右的数组进行快速排序
	public static void quickSort(int[] arr, int left, int right) {
		//递归结束的条件
		if (left >= right) {
			return;
		}
		int l = left;
		int r = right;
		//一次快速排序,arr[left]就是中心元素,用来对比,不变。 到最后全部对比完了,就交换位置
		while(l < r) {
			//右边从后往前,如果比中心元素大就继续向左走,直到比中心元素小
			while(l < r && arr[r] >= arr[left]) r --;
			//左边从前往后,如果比中心元素小就继续向右走,直到比中心元素大或相等
			while(l < r && arr[l] <= arr[left]) l ++;
			//如果 l < r 会一直执行上面的代码,
			if(l == r) { 	//说明r和l他们相遇了,那么就可以结束循环了:把中心元素放到r和l的位置,把这个位置的元素放到开头
				int temp = arr[r];	//存相遇的值
				arr[r] = arr[left];	//把相遇的地方变成中心元素
				arr[left] = temp;	//中心元素放上相遇的值(这个值一定会小于等于中心元素,在左边)
			}else {					//说明还没有相遇,把r和l换位置  此时他们位置相邻
				int temp = arr[r];//存右边的值
				arr[r] = arr[l];//右边的r值小于中心元素,放左边
				arr[l] = temp;//左边的l值小于中心元素,放右边
			}
		}
		quickSort(arr, left, l - 1);//执行左边 比刚才中心元素小的那一部分,再次快速排序
		quickSort(arr, r + 1, right);//执行右边 比刚才中心元素大的那一部分,再次快速排序
	}
}

归并排序:把数组分成一个数字一组,再两两比较合并。归并排序是多次将两个或两个以上的有序表合并成一个新的有序表。最简单的归并是直接将两个有序的子表合并成一个有序的表。

优点:稳定排序

package com.yc.test;
import java.util.Arrays;
public class MergeSort {
	public static void main(String[] args) {
		int[] arr = new int[]{8, 2, 5, -332, 15, 78};
		System.out.println(arr.length);
		//临时存储合并之后的数组
		int[] temp = new int[arr.length];
		mergeSort(arr, 0, arr.length - 1,temp);	
		System.out.println(Arrays.toString(arr));
	}
	//归并排序:先把数组中把每个数字分成一组,再对这些组两两排序合并
	public static void mergeSort(int[] arr, int left, int right, int[]temp) {
		if(left < right) {
			//把数组分开  mid为每次分开数组的中间索引,也就是从这里把两个分开
			int mid = (left + right) / 2;
			//递归调用,分完一次继续分,直到left=right,也就是一个数字一组
			mergeSort(arr, 0, 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; //临时数组的下标索引
		//先将两个部分合并。
		//条件是左边数组头部i(初始是0)还小于左边数组尾部mid;右边数组头部y(初始是mid + 1)小于右边数组尾部right
		while( i <= mid && j <= right) {  
			//左右两个数组的头部进行比较:小的拿出来;大的和下一个比.
			if(arr[i] <= arr[j]) {//如果左边头部小于右边头部
				temp[t] = arr[i];
				i++; t++;//然后左边索引往后面走,临时数组也往后面 + 1
			}else {//如果右边边头部小于左边头部
				temp[t] = arr[j];
				j++; t++;//然后右边索引往后面走,临时数组也往后面 + 1
			}
		}
		//如果右边部分拿完了(合并完了),左边部分还有剩余,则把剩下的都放到temp中
		//因为上一次排序一个数组排好序了,所以剩下的数字肯定都是比前面的的要大
		while(i <= mid) {  //如果左边不剩,那么前面的 i++会使 i > mid,能进这里,说明还有剩余
			temp[t] = arr[i];
			t++;i++;
		}
		//如果左边部分拿完了(合并完了),右边部分还有剩余,则把剩下的都放到temp中
		while(j <= right) {//如果右边不剩,那么前面的 j++会使 j > right,能进这里,说明还有剩余
			temp[t] = arr[j];
			t++;j++;
		}
		//接着将temp里面的数组填充到数组的指定位置
		t = 0;
		int templeft = left;
		while (templeft <= right) {//说明temp还没完全存入原arr数组的值
			arr[templeft] = temp[t];
			t++; templeft++;
		}
	}
}

基数排序:高级点的桶排序,按个位,十位,百位,千位,万位……的顺序依次比较;把数组中的数放在一个二维数组 一排桶 中

优点:速度很快,稳定。效率高的稳定性排序法

package com.yc.test;
import java.util.Arrays;
public class redixSort {
	public static void main(String[] args) {
		int[] arr = new int[]{5494,8, 2, 5, 9875, 15, 78,4567, 45,1564,456};
		redixSort(arr);	
		System.out.println(Arrays.toString(arr));//输出arr数组
	}
	/**
	 * 基数排序:就是高级点的桶排序,按个位,十位,百位,千位,万位……的顺序依次比较;把数组中的数放在一个二维数组 一排桶 中
	 * 速度很快,稳定。效率高的稳定性排序法
	 */
	public static void redixSort(int[] arr){
		//这个就是桶排,0~9共十个桶,每个桶里最多存放arr.length - 1 个数字
		int[][] bucket = new int[10][arr.length];
		int[] bucketElementCounts = new int[10];//代表每个桶,桶里有多少个数[4,5,0,7,7,5,9,5,2,3]
		//获得这个数组里最大的数
		int max = arr[0];
		for(int i = 0; i < arr.length; i++) {
			if(max < arr[i]) {max = arr[i];}}
		//把max转换成字符串,然后获得他的长度,就可以知道要做几次基数排序了
		int maxcount = (max + "").length();
		//i = 0时,进行个位排序;i = 1 时,进行十位排序;i = 2时,进行百位排序……
		for( int i = 0; i < maxcount; i++) {//开始基数排序,次数为maxcount
			for( int k = 0; k < arr.length; k++) {
				//获得这个数的相应的位数上的数字:i = 0时,获得个位;i = 1 时,获得十位;i = 2时,获得百位……
				int value = arr[k] / (int)Math.pow(10, i) % 10;
				//把这个数放进相应桶里的相应位置  】
				//假如个位数是7,那这个数第一次基数排序就应该放在bucket[7][1]
				//bucketElementCounts[value]表示第7个桶的数字:表示该排在这个位置的第几个
				bucket[value][bucketElementCounts[value]] = arr[k];
				bucketElementCounts[value]++;//第7个桶中数字数量 +1
			}
			int index = 0;
			for(int k = 0; k < bucketElementCounts.length; k++) {//遍历每个桶
				if(bucketElementCounts[k] != 0) {//每个桶的个数,这个桶里有数,就继续
					//遍历桶里的每个元素,把桶里的元素,放进原数组
					for(int x = 0; x < bucketElementCounts[k]; x++) {
						arr[index] = bucket[k][x];
						index ++;
					}
				}
				bucketElementCounts[k] = 0;//如果不把每一次的数字清零,下一次基数排序,会影响下一次排序
			}
		}
	}
}

各种排序方式的排序复杂度计算

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是C语言实现各种排序方法的代码示例: 1. 冒泡排序 ``` c void bubble_sort(int arr[], int n) { for (int i = 0; i < n - 1; i++) { for (int j = 0; j < n - i - 1; j++) { if (arr[j] > arr[j + 1]) { int temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } } ``` 2. 选择排序 ``` c void selection_sort(int arr[], int n) { for (int i = 0; i < n - 1; i++) { int min_index = i; for (int j = i + 1; j < n; j++) { if (arr[j] < arr[min_index]) { min_index = j; } } int temp = arr[i]; arr[i] = arr[min_index]; arr[min_index] = temp; } } ``` 3. 插入排序 ``` c void insertion_sort(int arr[], int n) { for (int i = 1; i < n; i++) { int key = arr[i]; int j = i - 1; while (j >= 0 && arr[j] > key) { arr[j + 1] = arr[j]; j--; } arr[j + 1] = key; } } ``` 4. 希尔排序 ``` c void shell_sort(int arr[], int n) { for (int gap = n / 2; gap > 0; gap /= 2) { for (int i = gap; i < n; i++) { int temp = arr[i]; int j; for (j = i; j >= gap && arr[j - gap] > temp; j -= gap) { arr[j] = arr[j - gap]; } arr[j] = temp; } } } ``` 5. 快速排序 ``` c void quick_sort(int arr[], int left, int right) { if (left < right) { int pivot = partition(arr, left, right); quick_sort(arr, left, pivot - 1); quick_sort(arr, pivot + 1, right); } } int partition(int arr[], int left, int right) { int pivot = arr[right]; int i = left - 1; for (int j = left; j < right; j++) { if (arr[j] < pivot) { i++; int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } } int temp = arr[i + 1]; arr[i + 1] = arr[right]; arr[right] = temp; return i + 1; } ``` 6. 归并排序 ``` c void merge_sort(int arr[], int left, int right) { if (left < right) { int mid = left + (right - left) / 2; merge_sort(arr, left, mid); merge_sort(arr, mid + 1, right); merge(arr, left, mid, right); } } void merge(int arr[], int left, int mid, int right) { int i = left, j = mid + 1, k = 0; int temp[right - left + 1]; while (i <= mid && j <= right) { if (arr[i] < arr[j]) { temp[k++] = arr[i++]; } else { temp[k++] = arr[j++]; } } while (i <= mid) { temp[k++] = arr[i++]; } while (j <= right) { temp[k++] = arr[j++]; } for (int m = left, n = 0; m <= right; m++, n++) { arr[m] = temp[n]; } } ``` 7. 堆排序 ``` c void heap_sort(int arr[], int n) { for (int i = n / 2 - 1; i >= 0; i--) { heapify(arr, n, i); } for (int i = n - 1; i > 0; i--) { int temp = arr[0]; arr[0] = arr[i]; arr[i] = temp; heapify(arr, i, 0); } } void heapify(int arr[], int n, int i) { int largest = i; int left = 2 * i + 1; int right = 2 * i + 2; if (left < n && arr[left] > arr[largest]) { largest = left; } if (right < n && arr[right] > arr[largest]) { largest = right; } if (largest != i) { int temp = arr[i]; arr[i] = arr[largest]; arr[largest] = temp; heapify(arr, n, largest); } } ``` 8. 计数排序 ``` c void counting_sort(int arr[], int n) { int max = arr[0], min = arr[0]; for (int i = 1; i < n; i++) { if (arr[i] > max) { max = arr[i]; } if (arr[i] < min) { min = arr[i]; } } int count[max - min + 1]; memset(count, 0, sizeof(count)); for (int i = 0; i < n; i++) { count[arr[i] - min]++; } for (int i = 1; i < max - min + 1; i++) { count[i] += count[i - 1]; } int temp[n]; for (int i = n - 1; i >= 0; i--) { temp[--count[arr[i] - min]] = arr[i]; } for (int i = 0; i < n; i++) { arr[i] = temp[i]; } } ``` 9. 桶排序 ``` c void bucket_sort(int arr[], int n) { int max = arr[0], min = arr[0]; for (int i = 1; i < n; i++) { if (arr[i] > max) { max = arr[i]; } if (arr[i] < min) { min = arr[i]; } } int bucket_num = (max - min) / n + 1; int bucket[bucket_num][n]; int bucket_count[bucket_num]; memset(bucket_count, 0, sizeof(bucket_count)); for (int i = 0; i < n; i++) { int index = (arr[i] - min) / n; bucket[index][bucket_count[index]] = arr[i]; bucket_count[index]++; } int k = 0; for (int i = 0; i < bucket_num; i++) { if (bucket_count[i] > 0) { insertion_sort(bucket[i], bucket_count[i]); for (int j = 0; j < bucket_count[i]; j++) { arr[k++] = bucket[i][j]; } } } } ``` 10. 基数排序 ``` c void radix_sort(int arr[], int n) { int max = arr[0]; for (int i = 1; i < n; i++) { if (arr[i] > max) { max = arr[i]; } } for (int exp = 1; max / exp > 0; exp *= 10) { counting_sort_by_digit(arr, n, exp); } } void counting_sort_by_digit(int arr[], int n, int exp) { int count[10]; memset(count, 0, sizeof(count)); for (int i = 0; i < n; i++) { count[(arr[i] / exp) % 10]++; } for (int i = 1; i < 10; i++) { count[i] += count[i - 1]; } int temp[n]; for (int i = n - 1; i >= 0; i--) { temp[--count[(arr[i] / exp) % 10]] = arr[i]; } for (int i = 0; i < n; i++) { arr[i] = temp[i]; } } ``` 以上是C语言实现各种排序方法的代码示例,可以根据具体的需求进行选择

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值