八大排序算法

目录

冒泡排序

选择排序

插入排序

希尔排序

基数排序

堆排序

快速排序

归并排序


冒泡排序

1、比较相邻的元素,如果第一个比第二个大,则交换两者。

2、每一轮都对每对相邻元素做比较交换,这样每轮结束,都会有一个最大数被排出来。

3、根据无序数组的长度选择轮数。

4、经过j轮后,排序完成,将无序数组排序成从小到大输出的有序数组。

JAVA代码如下:

//冒泡排序
package com.sort;

import java.util.Arrays;

public class BubbleSort {
	public static void main(String[] args) {
		int[] arr = new int[] { 5, 7, 4, 2, 0, 3, 1, 6, 9, 3, 8 };
		sort(arr);
		System.out.println(Arrays.toString(arr));
	}

	public static void sort(int[] arr) {
		for (int j = 0; j < arr.length; j++) {//轮数
			for (int i = 0; i < arr.length - 1; i++) {//游标移动比较交换
				if (arr[i] > arr[i + 1]) {
					int temp = arr[i];
					arr[i] = arr[i + 1];
					arr[i + 1] = temp;
				}
			}
		}
	}
}

冒泡排序平均时间复杂度:O(n^2)。

选择排序

找到最小值和待排序数组第一个交换。

假设待排序数组第一个就是最小值,之后从前到后去找有没有更小的,找到真正的最小值替代待排序数组第一的位置。

创建区域记录数组第一个的值和地址。每找到更小值时,用真正最小值将值代替,用真正最小值的地址将第一个值的地址代替。最后找到最小值时,将待排序数组第一的位置和真正的最小值进行交换。

JAVA代码如下:

//选择排序
package com.sort;

import java.util.Arrays;

public class SelectionSort {
	public static void main(String[] args) {
		int[] arr = new int[] { 5, 7, 4, 2, 0, 3, 1, 6, 9, 3, 8 };
		sort(arr);
		System.out.println(Arrays.toString(arr));
	}

	public static void sort(int[] arr) {
		//待排序数组第一个
		for (int i = 0; i < arr.length - 1; i++) {
			int minIndex = i;
			int min = arr[i];
			//待排序数组第一个后面的数依次和第一个进行比较
			for (int j = i + 1; j < arr.length; j++) {
				if (min > arr[j]) {
					min = arr[j];
					minIndex = j;
				}
			}
			//待排序数组第一的位置和真正的最小值进行交换。
			arr[minIndex] = arr[i];
			arr[i] = min;
		}
	}
}

选择排序平均时间复杂度:O(n^2)。

插入排序

认为数组中第一个位置是已经排好序的数组,然后用一个游标 i 指向第二个位置,定义游标 j=i-1,令j 和 j+1进行比较并不断前移依次和已排好序的数组中的数据进行比较,将其有序插入到已排好序数组中。

JAVA代码如下:

//插入排序
package com.sort;

import java.util.Arrays;

public class InsertSort {
	public static void main(String[] args) {
		int[] arr = new int[] { 5, 7, 4, 2, 0, 3, 1, 6, 9, 3, 8 };
		sort(arr);
		System.out.println(Arrays.toString(arr));
	}

	public static void sort(int[] arr) {
		//i不断右移,依次指向需要插入的数据
		for (int i = 1; i < arr.length; i++) {
			//j 和 j+1 进行比较,j不断前移达到依次进行比较的目的
			for (int j = i - 1; j >= 0; j--) {
				if (arr[j] > arr[j + 1]) {
					int temp = arr[j];
					arr[j] = arr[j + 1];
					arr[j + 1] = temp;
				} else {
					break;
				}
			}
		}
	}
}

插入排序的问题:当我们要插入的数据越小,移动的次数明显增多,效率也就越低。可以用希尔排序来优化这个问题。

插入排序平均时间复杂度:O(n^2)。

希尔排序

将小的数据放到前边,大的数据放到后边。

通过步长对数据进行分组,将步长设为数组长度的1/2,每次都能将每组在组内进行排序,小数值在前,大数值在后,然后通过改变步长,不断将步长变为上一次步长的1/2,不断调整排序,完成将整个数据排序的操作。

JAVA代码如下:

//希尔排序
package com.sort;

import java.util.Arrays;

public class ShellSort {
		public static void main(String[] args) {
			int[] arr = new int[] { 5, 7, 4, 2, 0, 3, 1, 6};
			ShellSort(arr);
			//sort(arr);
			System.out.println(Arrays.toString(arr));
		}
		public static void ShellSort(int[] arr) {
			for(int gap=arr.length/2;gap>0;gap/=2) {
				for(int i=gap;i<arr.length;i++) {
					for(int j=i-gap;j>=0;j-=gap) {
						if(arr[j]>arr[j+gap]) {
							int temp=arr[j];
							arr[j]=arr[j+gap];
							arr[j+gap]=temp;
						}
						else {
							break;
						}
					}
				}
				System.out.println(Arrays.toString(arr));
			}
		}
}

希尔排序平均时间复杂度:O(nlogn)。

基数排序

基数排序又称“桶子法”、“桶排序”。

分别通过将数据的个位、十位、百位……放入桶中,然后取出数据,经过将数据的各位都放入桶中再取出,即可将数据有序排列。

需要一个桶记录器来记录每个位数值上有几个数据存入,并且取出时,通过判断桶记录器是否为0即可判断每个位数值里有没有数,如果有数,在按顺序取出。

为了确保各个位数的排序不受其他位数排序的影响,每个位数排序完成后需要将桶记录器清空,即重新计数,在取出时,也之会取出各自位数排序时所放进去的数据。

JAVA代码如下:

//基数排序
package com.sort;

import java.util.Arrays;

public class RadixSort {
	public static void main(String[] args) {
		int[] arr = new int[] {1,5,11,13,26,87,46,68,123,225,8546};
		sort(arr);
		System.out.println(Arrays.toString(arr));
	}
	
	public static void sort(int[] arr) {
		//定义桶
		int[][] bucket=new int[10][arr.length];
		//定义桶记录器
		int[] elementCounts =new int[10];
		
		//找到数组中的最大值
		int max=arr[0];
		for(int i=0;i<arr.length;i++) {
			if(arr[i]>max) {
				max=arr[i];
			}
		}
		
		//找到最大值的位数
		int maxLength=(max+"").length();
		System.out.println("最大值位数:"+maxLength);
		int n=1;
		for(int h=0;h<maxLength;h++) {
			
			//向桶内放入数据
			for(int i=0;i<arr.length;i++) {
				int element =arr[i]/n %10;
				int count=elementCounts[element];
				bucket[element][count]=arr[i];
				elementCounts[element]=elementCounts[element]+1;
			}
			int index=0;
			//将桶内的数据取出
			for(int k=0;k<elementCounts.length;k++) {
				if(elementCounts[k] !=0) {
					for(int l=0;l<elementCounts[k];l++) {
						arr[index]=bucket[k][l];
						index++;
					}
				}
				//清空桶记录器
				elementCounts[k]=0;
			}
			n=n*10;
		}
	}
}

堆排序

//堆排序
package com.sort;

import java.util.Arrays;

public class HeapSort {
    public static void main(String[] args) {
        int[] arr = new int[] { 5, 7, 4, 2, 0, 3, 1, 6, 9, 3, 8 };
        // 构建大顶堆
        for (int p = arr.length - 1; p >= 0; p--) {
            sort(arr, p, arr.length);
        }

        // 堆底元素和堆顶元素进行互换,如何保证当前最大值不再参与构建。
        // 每有一次元素互换,就将构成大顶堆的数组长度减1。
        for (int i = arr.length - 1; i > 0; i--) {
            // 堆底元素和堆顶元素进行互换
            int temp = arr[0];
            arr[0] = arr[i];
            arr[i] = temp;

            sort(arr, 0, i);
        }
        
        System.out.println(Arrays.toString(arr));

    }

    public static void sort(int[] arr, int parent, int length) {
        int child = 2 * parent + 1;// 先定义左孩子,因为有孩子一定先有左孩子
        while (child < length) {// 程序是否执行的条件
            int rchild = child + 1;// 定义右孩子
            //child指向子节点最大值
            if (rchild < length && arr[rchild] > arr[child]) {
                child++;
            }
            // 父子节点的值进行对比交换
            if (arr[parent] < arr[child]) {
                int temp = arr[parent];
                arr[parent] = arr[child];
                arr[child] = temp;

                parent = child;
                child = 2 * child + 1;
            }
            // 某些情况下会陷入死循环,所以需要break跳出循环
            else {
                break;
            }
        }
    }
}

快速排序

package com.sort;

import java.util.Arrays;

public class QuickSort {
    public static void main(String[] args) {
        int[] arr = new int[] { 50, 23, 88, 35, 65, 53, 90, 13, 52, 42, 16, 18, 73, 25, 77, 66 };
        
        sort(arr, 0, arr.length - 1);
        System.out.println(Arrays.toString(arr));

    }

    public static void sort(int[] arr,int begin,int end) {
        int i,j;
        i=begin;
        j=end;
        while(i<j) {
            if(arr[i]>arr[i+1]) {
                int temp=arr[i];
                arr[i]=arr[i+1];
                arr[i+1]=temp;
                i++;
            }
            else if(arr[i]<arr[i+1]) {
                int temp=arr[i+1];
                arr[i+1]=arr[j];
                arr[j]=temp;
                j--;
            }
        }
        if(j-1>begin) sort(arr,begin,j-1);
        if(j+1<end)  sort(arr,j+1,end);
    }
    
}

归并排序

//归并排序
package com.sort;

import java.util.Arrays;

public class MergeSort {
    public static void main(String[] args) {
        int[] arr = new int[] { 5,1,4,2,0,3,7,6 };
        System.out.println("原数组:");
        System.out.println(Arrays.toString(arr));
        sort(arr,0,arr.length-1);
        System.out.println("排序后数组:");
        System.out.println(Arrays.toString(arr));
    }
    
//采用递归进行拆分    
    public static void sort(int[] arr,int left,int right) {
        if(left>=right) {
            return;
        }
        int mid=(left+right)/2;
        sort(arr,left,mid);
        sort(arr,mid+1,right);
        merage(arr,left,mid,right);
        
    }
    
//合并    
    public static void merage(int[] arr,int left,int mid,int right) {
        //定义出临时数组
        int[] temp=new int[right-left+1];
        //定义s1和s2
        int s1=left;
        int s2=mid+1;
        int i=0;//遍历临时数组
        //将数据写入到临时数据当中去
        while(s1<=mid &&s2<=right) {
            if(arr[s1]<=arr[s2]) {
                temp[i]=arr[s1];
                i++;
                s1++;
            }
            else {
                temp[i]=arr[s2];
                i++;
                s2++;
            }
        }
        //判断s1当中是否还有数据
        while(s1<=mid) {
            temp[i]=arr[s1];
            i++;
            s1++;
        }
        //判断s2当中是否还有数据
        while(s2<=right) {
            temp[i]=arr[s2];
            i++;
            s2++;
        }
        //将临时数组当中的数据放回原来数组
        for(int j=0;j<temp.length;j++) {
            arr[j+left]=temp[j];
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值