By the way,说一句,今晚我在写完快排的代码之后(11点左右),就被菜鸡讲师又叫去打杂了,真心难受,搞得我都快不想念研究生了。我忙完现在是1点半了,衷心奉劝各位还未考研的同志们,一定不要考研来沈阳某985大学的号称排名全国前几的控制专业,努努力去C9或者是南方的好大学吧,或者你能有毅力转行计算机那更不错了。
快速排序
快排一般分为两种实现方式,一种是挖坑法,一种是指针交换法,其中指针交换法代码较简洁一点。
挖坑法
public void quickSort(int[] arr,int start,int end){
if(start>=end) return;
int i=start;
int j=end;
int privot =arr[i];
while (i<j){
while (i<j&&arr[j]>=privot){
j--;
}
if(j>i){
arr[i]=arr[j];
i++;
}
while (i<j&&arr[i]<=privot){
i++;
}
if(j>i){
arr[j]=arr[i];
j--;
}
}
arr[i]=privot;
quickSort(arr,start,i-1);
quickSort(arr,i+1,end);
}
指针交换法
public void quickSort(int[] arr,int start,int end){
if(start>=end) return;
int i=start;
int j=end;
int privot =arr[i];
while (i<j){
while (i<j&&arr[j]>=privot){
j--;
}
while (i<j&&arr[i]<=privot){
i++;
}
if(i<j){
int tmp =arr[i];
arr[i]=arr[j];
arr[j]=tmp;
}
}
arr[start]=arr[i];
arr[i]=privot;
quickSort(arr,start,i-1);
quickSort(arr,i+1,end);
}
冒泡排序
冒泡其实很容易理解,每循环一次数组,都会把大元素往数组后面推,导致数组逐渐有序。
第一个循环是需要进行遍历的次数。如果arr只有2个元素,1次遍历比较即可;3个元素,2次遍历比较即可....依次类推,所以最外层循环终止条件是i<arr.length-1。
第二个循环时当前遍历要比较的次数。如果最开始i=0时,为了把最大的数冒泡到数组末端,需要做arr.length-1次比较。这时数组最后一个元素时确定的了,下一次循环需要做的比较次数就是arr.length-2了....依此类推,第二层循环终止条件是j<arr.length-1-i。
public void sort(int[] arr){
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]){
int tmp =arr[j];
arr[j]=arr[j+1];
arr[j+1]=tmp;
}
}
}
}
插入排序
插入排序就更为简单了,首先认为数组的第一个元素是有序的,从第二个元素开始,与第一个元素比较,如果第二个小于第一个,交换位置。这时,第一二个元素有序,从第三个元素....一直到数组完全有序。
public void sort(int[] arr){
for(int i=1;i<arr.length;i++){
int j=i;
while (j>0&&arr[j]<arr[j-1]){
int tmp =arr[j];
arr[j]=arr[j-1];
arr[j-1]=tmp;
j--;
}
}
}
选择排序
从数组中找出最小的元素放到第一个位置,然后从第二个位置开始,找出数组里最小的元素,放到第二个位置...
public void sort(int[] arr){
int index;
for(int i=0;i<arr.length;i++){
index=i;
for(int j=i;j<arr.length-1;j++){
if(arr[index]>arr[j+1]){
index=j+1;
}
}
if(index>i){
int tmp=arr[i];
arr[i]=arr[index];
arr[index]=tmp;
}
}
}
堆排序
推荐视频:https://www.bilibili.com/video/av47196993
视频讲解非常详细,这里就只提供Java代码实现和简要介绍了。
排序思路一共分三步:
a.将无需序列构建成一个堆,根据升序降序需求选择大顶堆或小顶堆;
b.将堆顶元素与末尾元素交换,将最大元素"沉"到数组末端;
c.重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复执行调整+交换步骤,直到整个序列有序。
heapfiy从当前位置开始,往下进行堆化。build_heap构建一个堆。swap交换元素位置。
public static void main(String[] args) {
int[] a = new int[]{3,4,5,6,212,9,5,0,36,4};
new HeapSort().heap_sort(a);
System.out.println();
}
public void heap_sort(int[] tree){
build_heap(tree,tree.length-1);//先构建一个堆 堆的顶层 也就是数组的第一个元素 是最大值
for(int i= tree.length-1;i>=0;i--){
swap(tree,i,0);
//把第一个元素和当前堆最后一个交换
//此时最后面的元素是当前堆中的最大值,拿出来,下一步计算不再考虑
heapfiy(tree,i,0);
// swap破坏了堆,因此剩下的数从parent=0的位置开始重新heapfiy,使得次大的数重新被推到堆顶
//这里的i是关键,刚好i从length-1开始,每次循环-1。
//对应每次循环,取出一个最大值,堆中元素减少一个,。
}
}
//构建一个堆要从最底层开始
public void build_heap(int[] tree,int n){
int last_node=n-1;//从它始
int parent =(last_node-1)/2;
for(int k=parent;k>=0;k--){
heapfiy(tree,n,k);
}
}
public void heapfiy(int[] tree,int n,int parent){
// int n=tree.length;
//n是堆中的节点个数
if(parent>=n) return;
int max =parent;
int lson=2*parent+1;
int rson=2*parent+2;
if(lson<n&&tree[lson]>tree[max]){
max=lson;
}
if(rson<n&&tree[rson]>tree[max]){
max=rson;
}
if(max!=parent) {
swap(tree,max,parent);
heapfiy(tree,n,max);
}
}