常用排序算法
1. 冒泡排序
- 冒泡排序的基本思想:通过对待排序序列从前向后(从下标较小的元素开始),依次比较相邻元素的值,若发现逆序则交换,使值较大的元素逐渐从前移向后部。
- 优化:因为排序的过程中,各元素不断接近自己的位置,如果一趟比较下来没有进行过交换,就说明序列有序,因此要在排序过程中设置一个标志flag判断元素是否进行过交换。
public class BubbleSort {
public static void main(String[] args) {
int arr[]={3, 9, -1, 10, 20};
System.out.println(Arrays.toString(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;
}
}
System.out.println(Arrays.toString(arr));
if (!flag){
break;
}else {
flag=true;
}
}
}
}
2. 选择排序
- 选择式排序也属于内部排序法,是从欲排序的数据中,按指定的规则选出某一元素,再依次规定交换位置后达到排序的目的。
- 排序思想:第一次从arr[0]-arr[n-1]中选取最小值,与arr[0]交换,第二次从arr[1]-arr[n-1]中选取最小值,与arr[1]交换,…,第n-1次从arr[n-2]~a[arr-1]中选取最小值,与arr[n-2]交换,总共通过n-1次,得到一个按排序码从小到大排列的有序序列。
public class SelectSort {
public static void main(String[] args) {
int [] arr = {101, 34, 119, 1, -1, 90, 123};
System.out.println("排序前:");
System.out.println(Arrays.toString(arr));
selectSort(arr);
System.out.println("排序后:");
System.out.println(Arrays.toString(arr));
}
public static void selectSort(int arr[]){
for (int i=0;i<arr.length-1;i++){
int min=arr[i];
int minIndex=i;
for (int j=i+1;j<arr.length;j++){
if(min>arr[j]){
min=arr[j];
minIndex=j;
}
}
if (minIndex!=i){
arr[minIndex]=arr[i];
arr[i]=min;
}
System.out.println("第"+(i+1)+"轮后~~");
System.out.println(Arrays.toString(arr));
}
}
}
3. 插入排序
- 插入排序属于内部排序,是对于欲排序的元素以插入的方式找寻该元素的适当位置,以达到排序的目的。
- 基本思想:把n个待排序的元素看成一个有序表和一个无序表,开始时有序表中包含一个元素,无需表中包含有n-1个元素,排序过程中每次从无序表中取出第一个元素,把他的排序码依次与有序元素的排序码进行比较,将他插入到有序表中的适当位置,使之成为新的有序表
public class InsertSort {
public static void main(String[] args) {
int arr[]={101, 34, 119, 1, -1, 90, 123};
System.out.println("排序前:");
System.out.println(Arrays.toString(arr));
InsertSort(arr);
System.out.println("排序后:");
System.out.println(Arrays.toString(arr));
}
public static void InsertSort(int arr[]){
int insertIndex=0;
int insertVal=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!=i-1){
arr[insertIndex+1]=insertVal;
}
System.out.println(Arrays.toString(arr));
}
}
}
4. 希尔排序
- 希尔排序也是一种插入排序,他是简单插入排序经过该井之后的一个更高效的版本,也成为缩小增量排序
- 希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件被分成一组,算法便终止。
public class ShellSort {
public static void main(String[] args) {
int arr[]={101, 34, 119, 1, -1, 90, 123};
System.out.println("排序前:");
System.out.println(Arrays.toString(arr));
shellSort(arr);
System.out.println("排序后:");
System.out.println(Arrays.toString(arr));
shellSort2(arr);
System.out.println("排序后:");
System.out.println(Arrays.toString(arr));
}
public static void shellSort(int arr[]){
int temp=0;
for (int grap=arr.length;grap>0;grap/=2){
for (int i=grap;i<arr.length;i++){
for (int j=i-grap;j>=0;j-=grap){
if (arr[j]>arr[j+grap]){
temp=arr[j];
arr[j]=arr[j+grap];
arr[j+grap]=temp;
}
}
}
}
}
public static void shellSort2(int arr[]){
int temp;
for (int grap=arr.length;grap>0;grap/=2) {
for (int i = grap; i < arr.length; i++) {
int j = i;
temp = arr[j];
if (arr[j] < arr[j - grap]) {
while (j-grap >= 0 && temp < arr[j - grap]) {
arr[j] = arr[j - grap];
j -= grap;
}
}
arr[j] = temp;
}
}
}
}
5. 快速排序
- 快速排序是对冒泡排序的一种改进,基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按次方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
public class QuickSort {
public static void main(String[] args) {
int arr[]={101, 34, 119, 1, -1, 90, 123};
System.out.println("排序前:");
System.out.println(Arrays.toString(arr));
quickSort(arr,0,arr.length-1);
System.out.println("排序后:");
System.out.println(Arrays.toString(arr));
}
public static void quickSort(int arr[],int low,int high){
if (low<high){
int index=getIndex(arr,low,high);
quickSort(arr,low,index-1);
quickSort(arr,index+1,high);
}
}
private static int getIndex(int[] arr, int low, int high) {
int temp=arr[low];
while(low<high){
while(low<high&&arr[high]>=temp){
high--;
}
arr[low]=arr[high];
while(low<high&&arr[low]<=temp){
low++;
}
arr[high]=arr[low];
}
arr[low]=temp;
return low;
}
}
6. 归并排序
- 归并排序是利用归并的思想实现的排序方法,该算法采用经典的分治策略(分治法将问题分成一些小的问题然后递归求解,而治的阶段则将分的阶段得到的各答案“修补”在一起,即分而治之)
public class MergeSort {
public static void main(String[] args) {
int arr[]={101, 34, 119, 1, -1, 90, 123};
int []temp=new int[arr.length];
System.out.println("排序前:");
System.out.println(Arrays.toString(arr));
mergeSort(arr,0,arr.length-1,temp);
System.out.println("排序后:");
System.out.println(Arrays.toString(arr));
}
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);
}
}
private static void merge(int[] arr, int left, int mid, int right, int[] temp) {
int i=left;
int j=mid+1;
int t=0;
while (i<=mid&&j<=right){
if (arr[i]<=arr[j]){
temp[t++]=arr[i++];
}else{
temp[t++]=arr[j++];
}
}
while (i<=mid){
temp[t++]=arr[i++];
}
while (j<=right){
temp[t++]=arr[j++];
}
int leftIndex=left;
t=0;
while (leftIndex<=right){
arr[leftIndex++]=temp[t++];
}
}
}
7. 基数排序
- 基数排序介绍
- 基数排序属于"分配式排序",又称"桶子法",通过键值的各个位的值,将要排序的元素分配至某些"桶"中,达到排序的作用
- 基数排序法是属于稳定性的排序,基数排序法的是效率高的稳定排序法
- 基本思想
- 将所有待比较数值统一为同样的数位长度,数位较短的数前面补0。然后,从最低位开始,一次进行一次排序。这样从最低位排序一直到最高位排序完成以后,数列就变成一个有序序列。
public class BucketSort {
public static void main(String[] args) {
int arr[]={53,3,542,748,14,214};
System.out.println("排序前:");
System.out.println(Arrays.toString(arr));
bucketSort(arr);
System.out.println("排序后:");
System.out.println(Arrays.toString(arr));
}
public static void bucketSort(int []arr){
int bucket[][]=new int[10][arr.length];
int max=arr[0];
for (int i=0;i<arr.length;i++){
if (max<arr[i]){
max=arr[i];
}
}
int bucketCounts[]=new int [10];
int maxLen=(max+"").length();
for (int i=0,n=1;i<maxLen;i++,n*=10) {
for (int j = 0; j < arr.length; j++) {
int digoutOfValue = arr[j] / n %10;
bucket[digoutOfValue][bucketCounts[digoutOfValue]] = arr[j];
bucketCounts[digoutOfValue]++;
}
int index = 0;
for (int k = 0; k < bucketCounts.length; k++) {
if (bucketCounts[k] != 0) {
for (int l = 0; l < bucketCounts[k]; l++) {
arr[index++] = bucket[k][l];
}
}
bucketCounts[k]=0;
}
System.out.println("第"+(i+1)+"轮排序"+Arrays.toString(arr));
}
}
}