1.

堆排序是一种优秀的排序算法,时间复杂度O(nlogn),主要思想是用数组构造一个最大堆,满足跟节点的value>子节点的value,然后将堆顶元素(value最大)与最后一个叶子节点交换,再调整堆,使其满足最大堆的性质,重复上述步骤n-1次后就得到一个有序序列。

 #include<iostream>
#include<cstdio>
#include<cstring>
#define MAX 111111
#define LEFT(i) (i << 1)
#define RIGHT(i) (i << 1|1)
using namespace std;
int a[MAX], Heap_Size, a_Length;
void Max_Heapify(int i){
int largest, l, r;
l = LEFT(i);
r = RIGHT(i);
if(l <= Heap_Size && a[l] > a[i]) largest = l;
else largest = i;
if(r <= Heap_Size && a[r] > a[largest]) largest = r;
if(largest != i){
int temp = a[i];
a[i] = a[largest];
a[largest] = temp;
Max_Heapify(largest);
}
return;
}
void Build_Heap(){
for(int i = a_Length/; i >= ; i --)
Max_Heapify(i);
return;
}
void Heap_Sort(){
Build_Heap();
for(int i = a_Length; i >= ; i --){
int temp = a[];
a[] = a[i];
a[i] = temp;
Heap_Size--;
Max_Heapify();
}
return ;
}
int main(){
freopen("data.cpp", "r", stdin);
freopen("out.cpp", "w", stdout);
while(~scanf("%d", &a_Length)){
Heap_Size = a_Length;
for(int i = ; i <= a_Length; i ++) scanf("%d", a+i);
Heap_Sort();
printf("Length = %d\n", a_Length);
for(int i = ; i < a_Length; i ++) printf("%d ", a[i]);
printf("%d\n\n\n", a[a_Length]);
}
return ;
}

2.

快速排序:主要思想就是随机选定一个数x,以该数为基准,将数组划分,左边都小于或等于它,右边都大于它,这样就将数组划分成左右两部分,而数x则是处于正确位置,然后再重复上述过程分别处理左右部分,直到数组有序。时间复杂度O(nlogn).

 #include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#define MAX 111111
using namespace std;
int a[MAX], a_length;
int Rand_Partition(int p, int r){
int x = a[r], i = p-;
for(int j = p; j < r; j ++){
if(a[j] <= x){
i ++;
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
a[r] = a[i+];
a[i+] = x;
return i+;
}
void Qucik_Sort(int p, int r){
if(p < r){                //与调用Rand_Partition()函数效果一样;
int i = p-;
for(int j = p; j < r; j ++){
if(a[j] <= a[r]){
i ++;
swap(a[i], a[j]);
}
}
swap(a[r], a[i+]);
int q = i+;             //end;
/* int q = Rand_Partition(p, r); */
Qucik_Sort(p, q-);
Qucik_Sort(q+, r);
}
}
int main(){
freopen("data.cpp", "r", stdin);
freopen("Quick_sort_out.cpp", "w", stdout);
while(~scanf("%d", &a_length)){
printf("Length = %d\n", a_length);
for(int i = ; i < a_length; i ++) scanf("%d", a+i);
Qucik_Sort(, a_length-);
for(int i = ; i < a_length-; i ++) printf("%d ", a[i]);
printf("%d\n\n\n", a[a_length-]);
}
return ;
}

3.

归并排序,采用分治策略,主要思想是假定数组a和b已经是有序的,那么可以在O(n)的时间内将他们合并成一个有序序列,现在将数组平均分成两部分,但这两部分并不是有序的,因此需要再次将这两个部分再分,使问题规模逐渐变小,继续递归划分,当子数组足够小时(即只有一个元素),可以直接求解,因为此时一个元素就是有序的。然后就可以合并这两个部分了,合并完之后就形成一个局部有序序列(我们最终要得到整个有序序列),此时向上回溯与其他有序部分进行合并,当回溯到跟节点时,整个序列就合并完毕,因此得到一个有序序列。

分治策略一般分为三步:(1):分解原问题使问题规模变小以便我们直接处理,对于上述问题就是将原序列分解,当分解到子序列只有一个元素时就可直接求解(因为一个元素的序列已经是有序的了);(2)治,即解决问题;(3)合并,将子问题解决之后要向上合并从而得到原问题的解。

分治策略一般使用递归来实现。

 #include<stdio.h>
#include<string.h>
int a[];
int l[];
int r[];
void merge(int p, int mid, int q)
{
int nl = mid - p + ;
int nr = q - mid;
int i, j, k;
for(i = ; i < nl; i ++)
l[i] = a[p+i];
for(i = ; i <= nr; i ++)
r[i - ] = a[mid+i];
l[nl] = << ;
r[nr] = << ;
i = ;
j = ;
for(k = p; k <= q; k ++)
{
if(l[i] <= r[j])
a[k] = l[i++];
else
a[k] = r[j++];
}
} void merge_sort(int l, int r)
{
if(l < r)
{
int mid = (l + r) >> ;
merge_sort(l, mid);
merge_sort(mid + , r);
merge(l, mid, r);
}
} int main(int argc, char const *argv[])
{
int n, i;
freopen("data.cpp", "r", stdin);
freopen("Merge_out.cpp", "w", stdout);
while(~scanf("%d", &n))
{
printf("Length = %d\n", n);
for(i = ; i < n; i ++)
scanf("%d", &a[i]);
merge_sort(, n-);
for(i = ; i < n-; i ++)
printf("%d ",a[i]);
printf("%d\n\n\n", a[i]);
}
return ;
}

4.

最后一个是用二叉搜索树通过中序遍历得到的有序序列,时间复杂度也是O(nlogn)较简单和容易理解。

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
using namespace std;
typedef struct Node{
int key;
Node *left;
Node *right;
Node(){
left = NULL;
right = NULL;
}
}Node;
Node *root;
stack<Node*>s;
void Insert(int key){
Node *tmp = new Node();
tmp->key = key;
Node *ff = root;
Node *flag = NULL;
while(ff){
flag = ff;
if(key <= ff->key) ff = ff->left;
else ff = ff->right;
}
if(flag == NULL){
root = new Node();
root->key = key;
return;
}
if(flag->key >= key) flag->left = tmp;
else flag->right = tmp;
} void Visist_Treee_1(Node *tmp){
if(tmp){
Visist_Treee_1(tmp->left);
printf("%d ", tmp->key);
Visist_Treee_1(tmp->right);
}
} /* void Visist_Treee_2(Node *tmp){ */
/* while(!s.empty()) s.pop(); */
/* s.push(tmp); */
/* while(!s.empty()){ */
/* Node *p = s.top(); */
/* s.pop(); */
/* while(p->left) s.push(p), p = p->left; */
/* Node *q = s.top(); */
/* s.pop(); */
/* printf("%d ", q->key); */
/* if(q->right) s.push(q); */
/* } */
/* } */ int main(){
int n, temp;
freopen("data.cpp", "r", stdin);
freopen("Binary_Tree_out.cpp", "w", stdout);
while(~scanf("%d", &n)){
root = NULL;
printf("Length = %d\n", n);
for(int i = ; i < n; i ++){
scanf("%d", &temp);
Insert(temp);
}
Visist_Treee_1(root);
printf("\n\n\n");
/* Visist_Treee_2(root); */
}
}

排序 O(nlogn)的更多相关文章

  1. 备战秋招之十大排序——O(nlogn)级排序算法

    时间复杂度O(nlogn)级排序算法 五.希尔排序 首批将时间复杂度降到 O(n^2) 以下的算法之一.虽然原始的希尔排序最坏时间复杂度仍然是O(n^2),但经过优化的希尔排序可以达到 O(n^{1. ...

  2. JS实现常用排序算法—经典的轮子值得再造

    关于排序算法的博客何止千千万了,也不多一个轮子,那我就斗胆粗制滥造个轮子吧!下面的排序算法未作说明默认是从小到大排序. 1.快速排序2.归并排序3.冒泡排序4.选择排序(简单选择排序)5.插入排序(直 ...

  3. js实现各种常用排序算法

    1.冒泡排序 var bubbleSort = function (arr) { var flag = true; var len = arr.length; for (var i = 0; i &l ...

  4. 常用的 JS 排序算法整理

    关于排序算法的问题可以在网上搜到一大堆,但是纯 JS 版比较零散,之前面试的时候特意整理了一遍,附带排序效率比较. //1.冒泡排序 var bubbleSort = function(arr) { ...

  5. 我们一起来排序——使用Java语言优雅地实现常用排序算法

    破阵子·春景 燕子来时新社,梨花落后清明. 池上碧苔三四点,叶底黄鹂一两声.日长飞絮轻. 巧笑同桌伙伴,上学径里逢迎. 疑怪昨宵春梦好,元是今朝Offer拿.笑从双脸生. 排序算法--最基础的算法,互 ...

  6. Java实现:数据结构之排序

    Java实现:数据结构之排序 0.概述 形式化定义:假设有n个记录的序列(待排序列)为{ R1, R2 , -, Rn },其相应的关键字序列为 { K1, K2, -, Kn }.找到{1,2, - ...

  7. 各种排序算法的总结、比较与Java实现

    1 快速排序(QuickSort) 快速排序是一个就地排序,分而治之,大规模递归的算法.从本质上来说,它是归并排序的就地版本.快速排序可以由下面四步组成. (1) 如果不多于1个数据,直接返回.(2) ...

  8. 九度OJ 1349:数字在排序数组中出现的次数 (排序、查找)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:2489 解决:742 题目描述: 统计一个数字在排序数组中出现的次数. 输入: 每个测试案例包括两行: 第一行有1个整数n,表示数组的大小. ...

  9. 几种常见排序算法的java实现

    一.几种常见的排序算法性能比較 排序算法 最好时间 平均时间 最坏时间 辅助内存 稳定性 备注 简单选择排序 O(n^2) O(n^2) O(n^2) O(1) 不稳定 n小时较好 直接插入排序 O( ...

随机推荐

  1. objective-c内存管理中autorelease的作用

    //创建自动释放池 @autoreleasepool { //autorelease会将对象放入自动释放池中,并返回该对象本身 //当自动释放池销毁时,将自动调用对象的release方法 Person ...

  2. java新手笔记8 包

    1.main函数 public class MainParam { //考察main 方法的参数 args //运行时可以传入参数 参数类型 String public static void mai ...

  3. a标签的href="javascript:void(0)"和href="#"的区别

    修正一个说法上的bug吧.对于IE6来说,点击后gif暂停bug仅仅发生在“javascript:伪协议未加分号”的情形下. 我再来提供一个视角吧. 给<a>标签增加href属性,就意味着 ...

  4. 设置contentType

    //定义编码 header( 'Content-Type:text/html;charset=utf-8 '); //Atom header('Content-type: application/at ...

  5. 九度OJ 1076 N的阶乘 -- 大数运算

    题目地址:http://ac.jobdu.com/problem.php?pid=1076 题目描述: 输入一个正整数N,输出N的阶乘. 输入: 正整数N(0<=N<=1000) 输出: ...

  6. nodejs实现单文件上传。

    new了formidable的一个实例. formidable模块可以直接捕获当前数据流的状态并返回文件路径. 主要使用了file事件和end事件. var form = new formidable ...

  7. jQuery DataTables 插件使用笔记

    初始化 在页面中 <!DOCTYPE html> <html> <head> <link rel="stylesheet" type=&q ...

  8. PL/SQL学习(五)异常处理

    原文参考:http://plsql-tutorial.com/ 组成: 1) 异常类型 2) 错误码 3) 错误信息   代码结构: DECLARE Declaration section BEGIN ...

  9. WPF窗体禁用最大化按钮

    禁用WPF窗体的最大化按钮可以使用Windows API改变按钮状态的方法实现.使用GetWindowLong可以得到当前按钮的状态.使用SetWindowLong可以设置按钮的状态.使用SetWin ...

  10. App 性能分析

    关键因素: ---- Instrument 性能分析神器 1. 启动时间 应用启动时间长短对用户第一次体验至关重要,同时系统对应用的启动.恢复等状态的运行时间也有严格的要求,在应用超时的情况下系统会直 ...