时间复杂度为on的排序算法_平均时间复杂度为O(nlogn)的排序算法

本文包括

1.快速排序

2.归并排序

3.堆排序

1.快速排序

快速排序的基本思想是:采取分而治之的思想,把大的拆分为小的,每一趟排序,把比选定值小的数字放在它的左边,比它大的值放在右边;重复以上步骤,直到每个区间只有一个数。此时数组已经排序完成。

快速排序最重要的是partition函数功能的实现,也就是将比选定基数小的值放在他的左边,比选定基数大的值放在它的右边的功能函数。

熟悉快速排序的人也许都会有自己的partition函数的写法。此处,提供两种不同的partition函数写法。

例1:

public void partition(int[] a,int start,intend){if(start>=end)return;int low=start;int high=end;int index = a[low];//选定基数

while(lowindex && high>low)//找到右边比基数小的数字

high--;if(low

a[low++] =a[high];while(a[low]low)//找到左边比基数大的数字

low++;if(low

a[high--] =a[low];

}

a[low]=index;

partition(a,start,low-1);

partition(a,low+1,end);

}

例2:

public void partition1(int[] a,int start,intend){if(start>=end)return;int index =start;

swap(a[index],a[end]);int small=start-1;for(index = start;index

small ++;if(small!=index){

swap(a[small],a[index]);

}

}

}

small++;

swap(a[small],a[end]);

partition1(a,start,small-1);

partition1(a,small+1,end);

}

快速排序

public void quickSort(int[] a){

partition1(a,0,a.length-1);

}

快速排序的时间复杂度为O(nlogn),最坏时间复杂度为O(n^2),最坏的情况适之每次区间划分的结果都是基准关键字的最左边或者右边,即选择的数字是待排序列中最小或者最大的。当n较大时使用较好。

2.归并排序

归并排序是利用递归与分治技术将数据序列划分为越来越小的半子表,再对半子表进行排序,最后在利用递归方法将排好序的半子表合并成为越来越大的有序序列。

归并排序中的归,就是递归的意思,递归将数组分成小的字数组。

例如数组[13,6,8,11]

先将数组分成[13,6],[8,11]两个数组,再将数组分为[13],[6],[8],[11]。然后进行合并,[6,13],[8,11],最后合并为[6,8,11,13]。

因为归并排序需要将数组元素分割存储,所以空间复杂度为O(n),是以空间换时间的做法。

public void Merge(int[] a,int start,int mid,intend){int length1,length2; //新数组的大小

inti,j,k;

length1= mid - start + 1;

length2= end -mid;int[] L = new int[length1];int[] R = new int[length2];for(i=0,k=start;i

L[i] =a[k];for(i=0,k=mid+1;i

R[i] =a[k];for(k=start,i=0,j=0;i

if(L[i]

a[k]=L[i];

i++;

}else{

a[k]=R[j];

j++;

}

}if(i

for(j=i;j

a[k]=L[j];if(j

for(i=j;i

a[k]=R[i];

}

调用归并排序。

public void MergeSort(int[] a,int start,intend){if(start1){int mid = (start+end)/2;

MergeSort(a,start,mid);

MergeSort(a,mid+1,end);

Merge(a,start,mid,end);

}

}

归并排序的时间复复杂度为O(nlogn),且归并排序是稳定的排序算法,适合n较大时使用。虽然归并排序时间复杂度较低且具有稳定性,但因为其利用了O(n)的空间存储数据,所以使用的时候需要综合考虑。

3.堆排序

堆是一种特殊的树形数据结构,每个节点都有一个值,通常提到的堆是一棵完全二叉树,根节点的值小于或大于两个节点的值,同时根节点的两个子树也分别是两个堆。

堆排序的思想是对于给定的n个记录,初始时把这些记录看作成一棵顺序的二叉树,然后将其调整为一个大顶堆,将堆的最后一个元素与堆顶的元素进行交换后,堆的最后一个元素即为最大元素;接着将前(n-1)个元素重新调整为一个大顶堆,再将堆顶元素与当前堆的最后一个元素进行交换后得到次大的记录,重复该过程知道调整的堆中只剩下一个元素为止。此时已经得到一个有序的数组。

简要来说,堆排序就是两个过程:构建堆;交换堆顶元素与最后一个元素的值。

public void adjustHeap(int[] a,int pos,intlen){inttemp;intchild;for(temp = a[pos];2 * pos+1<=len;pos=child){

child= 2 * pos+1;//得到子节点的下标

if(child

child++;if(a[child] > temp)//将子节点和父节点进行交换

a[pos] =a[child];else

break;

}

a[pos]=temp;

}//堆排序

public void HeapSort(int[] a){for(int i=a.length/2-1;i>=0;i--)//构建堆

adjustHeap(a,i,a.length-1);for(int i=a.length-1;i>=0;i--){//把第一个数字和最后一个数字交换

int temp = a[0];

a[0] =a[i];

a[i]=temp;//调整堆保证第一个数字是最大的

adjustHeap(a,0,i-1);//调整剩下i-1个元素

}

}

堆排序的时间复杂度也为O(nlogn),同样适合n较大时使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值