最近要准备春招实习,复习各种知识点,准备用博客记录一下,就从排序算法开始吧。
排序算法是所有算法中很重要的一类,也是很经典的面试问题。首先我们将排序算法进行分类和进行时间和空间复杂度分析。
本文分析的排序算法包括:简单(直接)插入排序、希尔排序、(直接)选择排序、堆排序、冒泡排序、快速排序、归并排序。
package SortAlgorithm;
//排序抽象类
public abstract class Sort {
public static int[] nums = {1, 3, 4, 5, 2, 6, 9, 7, 8, 0};//定义待排序数组
public static int i,j,k,temp,key,min,gap;
public static void printArry(int[] arr){
for(i=0;i<arr.length;i++){
System.out.print(arr[i]+" ");
}
System.out.println();
}
//(1)冒泡排序
public static void bubbleSort(int[] arr){
for(i=0;i<arr.length-1;i++){ //n个数字循环n-1轮
for(j=0;j<arr.length-i-1;j++){
if(arr[j]>arr[j+1]){
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
//(2)选择排序
public static void selectSort(int[] arr){
for(i=0;i<arr.length;i++){ //每一轮的第一个位置
min = i;
for(int j=i+1;j<arr.length;j++){
if(arr[min]>arr[j]){
min = j; //每一轮找到最小的数放到当前轮的第一个位置
}
}
temp = arr[i];
arr[i] = arr[min];
arr[min] = temp;
}
}
//(3)插入排序
public static void insertSort(int[] arr){
for(i=1;i<arr.length;i++){
temp = arr[i]; //取出待插入的数
for(j=i-1;j>=0;j--){ //找到待插入的数组的位置
if(temp<arr[j]){
arr[j+1] = arr[j]; //如果当前位置的数比待插入的数大,则当前数向后移一位
}else
break;
}
arr[j+1] = temp;
}
}
//(4)快速排序
public static void quickSort(int[] arr,int l,int r){
if(l>r)return;
key = arr[l];
i=l;
j=r;
while(i<j){
if(i>=j)break; //可以节省arr[j] = arr[i];arr[i] = arr[j];两步
while(i<j&&arr[j]>=key)j--; //千万不要忘记等号!!!
arr[i] = arr[j];
while(i<j&&arr[i]<=key)i++;
arr[j] = arr[i];
}
arr[i] = key;
quickSort(arr,l,i-1);
quickSort(arr,i+1,r);
}
//(5)希尔排序
public static void shellSort(int[] arr){
gap = arr.length;
while(gap>1){ //每次确定间隔大小直到间隔为一,等同于整体数组插入排序
gap = gap/3+1;
for(i=gap;i<arr.length;i++){ //插入排序,间隔为gap
int temp = arr[i];
for(j=i-gap;j>=0;j-=gap){
if(temp<arr[j]){
arr[j+gap] = arr[j];
}else
break;
}
arr[j+gap] = temp;
}
}
}
//(6)堆排序
//调整堆
public static void heapAdjust(int[] arr, int parent,int length){
temp = arr[parent]; //保存父节点
int child = parent*2+1; //得到左子节点
while(child<length){
if(child+1<length&&arr[child+1]>arr[child])
child++; //找到最大的子节点
if(temp>arr[child])
break;
arr[parent] = arr[child];
parent = child; //往下继续调整
child = parent*2+1;
}
arr[parent] = temp;
}
public static void heapSort(int[] arr){
for(int i=arr.length/2-1;i>=0;i--){ //初始化堆
heapAdjust(arr,i,arr.length);
}
for(int i=arr.length-1;i>0;i--){
temp = arr[i];
arr[i] = arr[0]; //将最大值放到最后,最后一个较小的值放到堆顶然后进行调整
arr[0] = temp;
heapAdjust(arr,0,i);
}
}
//(7)归并排序
public static void mergeSort(int[] arr,int start,int end){
int mid = (start+end)/2;
if(start<end){ //递归终止条件
mergeSort(arr,start,mid); //递归的将数据划分为两部分
mergeSort(arr,mid+1,end);
i = start; //要合并的两部分的开始下标
j = mid+1;
k = 0;
int[] temp = new int[end-start+1]; //申请临时空间
while(i<=mid&&j<=end){ //对两部分进行合并
if(arr[i]<arr[j]) //首先将较小的放入,下标后移
temp[k++] = arr[i++];
else
temp[k++] = arr[j++];
}
while(i<=mid) //如果第一部分还有剩余,全部拷贝到临时数组中
temp[k++] = arr[i++];
while(j<=end) //如果第二部分还有剩余,全部拷贝到临时数组中
temp[k++] = arr[j++];
k = 0;
for(int i=start;i<=end;i++) //从临时数组中拷贝回原数组中
arr[i] = temp[k++];
}
}
public static void main(String[] args){
bubbleSort(nums);
printArry(nums);
selectSort(nums);
printArry(nums);
insertSort(nums);
printArry(nums);
quickSort(nums,0,nums.length-1);
printArry(nums);
shellSort(nums);
printArry(nums);
heapSort(nums);
printArry(nums);
mergeSort(nums,0,nums.length-1);
printArry(nums);
}
}