平均时间复杂度为O(nlogn)的排序算法
本文包括
1.快速排序
2.归并排序
3.堆排序
1.快速排序
快速排序的基本思想是:采取分而治之的思想,把大的拆分为小的,每一趟排序,把比选定值小的数字放在它的左边,比它大的值放在右边;重复以上步骤,直到每个区间只有一个数。此时数组已经排序完成。
快速排序最重要的是partition函数功能的实现,也就是将比选定基数小的值放在他的左边,比选定基数大的值放在它的右边的功能函数。
熟悉快速排序的人也许都会有自己的partition函数的写法。此处,提供两种不同的partition函数写法。
例1:
public void partition(int[] a,int start,int end){
if(start>=end)
return ;
int low=start;
int high=end;
int index = a[low];//选定基数
while(low<high){
while(a[high]>index && high>low)//找到右边比基数小的数字
high--;
if(low<high)
a[low++] = a[high];
while(a[low]<index && high>low)//找到左边比基数大的数字
low++;
if(low<high)
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,int end){
if(start>=end)
return ;
int index = start;
swap(a[index],a[end]);
int small=start-1;
for(index = start;index<end;index++){
if(a[index]<a[end]){//若比选定基数小,则与前面比大于基数的数字进行交换
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,int end){
int length1,length2; //新数组的大小
int i,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<length1;i++,k++)//将前半部分数组存入L中
L[i] = a[k];
for(i=0,k=mid+1;i<length2;i++,k++)//将后半部分数组存入R中
R[i] = a[k];
for(k=start,i=0,j=0;i<length1&&j<length2;k++){//分别从两个数组中读取数据,取较小的放入员数组中
if(L[i]<R[j]){
a[k] = L[i];
i++;
}
else{
a[k] = R[j];
j++;
}
}
if(i<length1)//将L中还有的剩余数字存入原数组
for(j=i;j<length1;j++,k++)
a[k] = L[j];
if(j<length2)//将R中还有的剩余数字存入元素族
for(i=j;i<length2;i++,k++)
a[k] = R[i];
}
调用归并排序。
public void MergeSort(int[] a,int start,int end){
if(start<end && a.length>1){
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,int len){
int temp;
int child;
for(temp = a[pos];2 * pos+1<=len;pos=child){
child = 2 * pos+1;//得到子节点的下标
if(child<len&&a[child]<a[child+1])//得到子节点中较大的节点
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较大时使用。
平均时间复杂度为O(nlogn)的排序算法的更多相关文章
- 时间复杂度为O(nlogn)的排序算法
时间复杂度为O(nlogn)的排序算法(归并排序.快速排序),比时间复杂度O(n²)的排序算法更适合大规模数据排序. 归并排序 归并排序的核心思想 采用"分治思想",将要排序的数组 ...
- 备战秋招之十大排序——O(nlogn)级排序算法
时间复杂度O(nlogn)级排序算法 五.希尔排序 首批将时间复杂度降到 O(n^2) 以下的算法之一.虽然原始的希尔排序最坏时间复杂度仍然是O(n^2),但经过优化的希尔排序可以达到 O(n^{1. ...
- 时间复杂度为O(nlogn)的LIS算法
时间复杂度为 n*logn的LIS算法是用一个stack维护一个最长递增子序列 如果存在 x < y 且 a[x] > a[y],那么我们可以用a[y]去替换a[x] 因为a[y]比较小 ...
- 8种主要排序算法的C#实现
作者:胖鸟低飞 出处:http://www.cnblogs.com/fatbird/ 简介 排序算法是我们编程中遇到的最多的算法.目前主流的算法有8种. 平均时间复杂度从高到低依次是: 冒泡排序(o( ...
- 排序算法的C#实现
8种主要排序算法的C#实现 新的一年到了,很多园友都辞职要去追求更好的工作环境,我也是其中一个,呵呵! 最近闲暇的时候我开始重温一些常用的算法.老早就买了<算法导论>,一直都没啃下去. ...
- 8种主要排序算法的C#实现 (一)
简介 排序算法是我们编程中遇到的最多的算法.目前主流的算法有8种. 平均时间复杂度从高到低依次是: 冒泡排序(o(n2)),选择排序(o(n2)),插入排序(o(n2)),堆排序(o(nlogn)), ...
- 利用反射快速给Model实体赋值 使用 Task 简化异步编程 Guid ToString 格式知多少?(GUID 格式) Parallel Programming-实现并行操作的流水线(生产者、消费者) c# 无损高质量压缩图片代码 8种主要排序算法的C#实现 (一) 8种主要排序算法的C#实现 (二)
试想这样一个业务需求:有一张合同表,由于合同涉及内容比较多所以此表比较庞大,大概有120多个字段.现在合同每一次变更时都需要对合同原始信息进行归档一次,版本号依次递增.那么我们就要新建一张合同历史表, ...
- JavaScript 数据结构与算法之美 - 十大经典排序算法汇总(图文并茂)
1. 前言 算法为王. 想学好前端,先练好内功,内功不行,就算招式练的再花哨,终究成不了高手:只有内功深厚者,前端之路才会走得更远. 笔者写的 JavaScript 数据结构与算法之美 系列用的语言是 ...
- JavaScript实现各种排序算法
前言:本文主要是用JavaScript实现数据结构中的各种排序算法,例如:插入排序.希尔排序.合并排序等. 冒泡排序 function bubbleSort(arr) { console.time(& ...
随机推荐
- python学习之day9
队列queue 队列是线程安全的,它保证多线程间的数据交互的一致性. 先进先出队列Queue import queue q = queue.Queue(maxsize=3) #maxsize为队列最大 ...
- Python每日一练(3):爬取百度贴吧图片
import requests,re #先把要访问URL和头部准备好 url = 'http://tieba.baidu.com/p/2166231880' head = { 'Accept': '* ...
- TC基础使用指南(基于xbeta的TC配置文件)
所有常用目录都可以通过ctrl+d加一个或几个字母的超快捷方式直接跳转到位. 按下BackSpace键,就可以进入到上一级目录 Ctrl+q 在右侧打开左侧选定文件,再按一次Ctrl+q退出 按 Ct ...
- IT第七天 - 类及其属性、方法的理解,断点调试初识,代码优化总结,编程逻辑培养
IT第七天 上午 类 1.对象:是多个实体抽象出来的共同点集合,对象包括:属性(即实体的特征).方法(即尸体的功能作用) 2.程序中,用类来模拟对象 3.类是抽象的,是对象的类型,是将多个拥有相同属性 ...
- poj 1979 Red and Black(dfs)
题目链接:http://poj.org/problem?id=1979 思路分析:使用DFS解决,与迷宫问题相似:迷宫由于搜索方向只往左或右一个方向,往上或下一个方向,不会出现重复搜索: 在该问题中往 ...
- SQL查询各阶段的统计信息
我们经常会遇到各种分类统计问题,须要将这些结果一次显示出来.这次老师提出的要求是我想看60分下面多少人.60~70多少人,70~80多少人.80~90多少人,90~100多少人.他们曾 ...
- uVa 714 (二分法)
Time Limit:3000MS Memory Limit:0KB 64bit IO Format:%lld & %llu Description Before th ...
- ZOJ 3331 Process the Tasks 双塔Dp
用dp[i][j]表示当前安排好了前i个任务,且机器A和机器B完成当前分配到的所有任务的时间差为j(这里j可正可负,实现的时候需要加个offset)时,完成这些任务的最早时间.然后根据j的正负,分别考 ...
- ASP.NET MVC进阶之路:深入理解Controller激活机制并使用Ioc容器创建对象
本文标题说是"深入理解Controller"其实有点“标题党”的味道了.本篇只会探讨"Controller"的激活机制,也就是如何创建Controller的并调 ...
- 由动态库文件dll生成lib库文件(手动生成.def文件,然后使用lib命令编译,非常牛),同理可使用dll生成.a库文件
本文基于OpenBlas的编译和安装,来说明如何从一个dll文件生成lib库文件. 参考OpenBlas的说明“Howto generate import library for MingW”,和Mi ...