冒泡排序: 时间复杂度o(n^2)
原理是临近的数字两两进行比较,按照从小到大或者从大到小的顺序进行交换,这样一趟过去后,最大或最小的数字被交换到了最后一位,然后再从头开始进行两两比较交换,直到倒数第二位时结束
public void sort(int [] a){
for(int i =0;i < a.length;i++ ){
for(int j =1;i< a.length-1;j++){
if(a[j]< a[j-1]){
//相邻两个元素的遍历,每次只能得到一个最小值或者最大值
swap(a[j] , a[j-1]);
}
}
}
}
选择排序 o(n^2)
第1趟,在待排序记录r[1]~~r[n]中选出最小的记录,将它与r[1]交换;第2趟,在待排序记录r[2]~r[n]中选出最小的记录,将它与r[2]交换;以此类推,第i趟在待排序记录r[i]~r[n]中选出最小的记录,将它与r[i]交换,使有序序列不断增长直到全部排序完毕。
void sort(int [] a){
for(int i =0;i < a.length ; i++){
int min =i;//
for (int j =i+1; j < a.length ;j++){
if(a [j] > a[min]){
//一次遍历得到最小值的坐标。和之前的最小值交换
min =j;
}
}
swap(a[i], a[min]);
}
}
插入排序 o(n^2)
给定序列,存在一个分界线,分界线左边默认有序,右边默认无序(初始时默认第一个元素有序),每次取右边无序的第一个元素和左边有序的比较,并插入到左边合适的位置,分界线右移一位。
public void sort( int [] a){
int j =0;
for (int i =1 ;i < a.length ; i++){
//默认a[i] 之前为有序序列
if(a[i] <a[i-1]){
int temp =a[i];
//把 a[i] 插入到a[i-1]之前有序序列的合适位置上去-->
for( j=i-1;j >0&& a[j]>temp ;j--){
a[j+1] =a[j];
}
a[j+1] =temp;
}
}
}
希尔排序
定义一个增量,把序列按增量分组,对每组使用直接插入排序算法排序,然后增量递归的进行递减;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
public void sort(int [] a){
int j =0,split =a.length;
//split 为定义的增量,每次排序完成后split/2 直至split 为0时排序结束
while(split>0){
split =split/2;
for( int i =split ;i <a.length ;i++){
if(a[i] <a[i -split]){
int temp =a[i];
for( j =i-split ; j>0&& a[j]>temp ;j=j-split){
a[j+split] =a[j];
}
a[j+split] =temp;
}
}
}
}
堆排序 o(nlog^n)
堆排序利用的数据结构是完全二叉树,对于一颗完全二叉树 ,他的任意一个节点i的左右子节点是 2*i+1 2*i+2(如果节点存在的话) 堆分为大根堆和小根堆,是完全二叉树。大根堆的要求是每个节点的值都不大于其父节点的值。
基本思路是,构建一个完全二叉树,把他变成大根堆,然后每次把根节点(即最大值)移除,用最后的节点替代,这时数组长度减一继续构建大根堆。
public void sort( int [] a){
//最后一个节点的坐标是 a[a.length/2-1],一次添加构建大根堆
for( int j =a.length/2-1 ;j>0 ;j--){//先把数组构建成大根堆
makeMax(a,j,a,length)
}
for (int i =a.length-1 ;i > 1;i--){
swap(a[i],a[0]); //把大根堆的最大元素取出,放在数组末尾
makeMax(a,0 ,i); //重新构建大根堆
}
}
//构建大根堆,从根节点遍历,如果左右子叶大于根节点,则交换。
//
publci void makeMax(int [] a ,int start,int end){
int temp=a[start]; //根节点
int j =2*start+1; //左子叶
while(j< end){
if(j+1 < end && a[j]< a[j+1]){ //找到左右子叶中比较大的
j++;
}
if(temp > a[j]){
break; //当前节点大于左右子叶,跳出
}
a[start] =a[j];
start =j; //节点和子叶均指向交换后的下一个节点和子叶
j=2*j+1;
}
a[start] =temp;
}
归并排序 o(nlog^n)
将数组分成二组,如果这两组,如果这两组组内的数据都是有许多,那么就可以很方便的将这二组排序。如果这二组无序,就将这二组继续分成两组排序,当组里只有一个元素时是有序的,可以和相邻的元素合并
public void sort(int [] a ){
int temp=new int[a.length];
mergesort(a,0,a.length,temp);
}
public void mergesort(int [] a,int start ,int end ,int []temp){
if(end >start){
int middle =(end-start)/2;
mergesort(a,start,middle,temp);
mergesort(a,middle,end,temp);
mergearray(a,start,middle,end,temp);
}
}
public void metgearray(int [] a,int start,int middle,int end,int temp){
int i=j=k=l;
whle(i < start &&j< end){
if(a[j]>a[i]){
temp[k++]=a[j++];
}else{
temp[k++]=a[i++];
}
}
if(i< start ){
temp[k++]=a[i++];
}
if(j< end){
temp [k++]=a[k++];
}
for (i =0;i< k;i++){
a[start+i]=temp[i];
}
}
快速排序 o(nlog^n -n^2)
通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
public void sort(int []a){
mergesort(a,0,a.length);
}
public void mergesort(int [] a ,int start ,int end){
while(start <end){
//得到中间数,数组左边的数比他小,右边的比他大
int middle =mergearray(a,start,end);
mergesort(a,start,middle);
mergesort(a,middle,end);
}
}
public void mergearray(int [] a,int start ,int end){
int mid=a[start]; //默认第一个
int i=stat;j=end;
while(i<j){
while (i<j&&a(j)>mid){
//从后向前遍历,找到第一个小于mid的元素,放在i处
j--;
}
if(j>i){
a[i]=a[j];
i++;
}
while(i<j&&a(i)<mid){
//从前向后遍历,找到第一个大于mid的元素,放在j处
i++;
}
if(j>i){
a[j]=a[i];
j--;
}
}
a[i]=temp; //此时 i=j
return i;
}