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. IOS-开发日志-UIScrollView

    UIScrollView 1.  contentOffset 默认CGPointZero,用来设置scrollView的滚动偏移量. // 设置scrollView的滚动偏移量 scrollView. ...

  2. 互联网金融爬虫怎么写-第一课 p2p网贷爬虫(XPath入门)

    版权声明:本文为博主原创文章,未经博主允许不得转载. 相关教程: 手把手教你写电商爬虫-第一课 找个软柿子捏捏 手把手教你写电商爬虫-第二课 实战尚妆网分页商品采集爬虫 手把手教你写电商爬虫-第三课 ...

  3. Token 的作用

    Token,就是令牌,最大的特点就是随机性,不可预测.一般黑客或软件无法猜测出来. 那么,Token有什么作用?又是什么原理呢? Token一般用在两个地方: 1)防止表单重复提交. 2)anti c ...

  4. 学习基于OpenGL的CAD程序的开发计划(一)

    本人目前从事的工作面对的客户中很多来自高端制造业,他们对CAD/CAE/CAM软件的应用比较多.公司现有的软件产品主要是用于渲染展示及交互,但面对诸如CAD方面的应用(比如基于约束的装配.制造工艺的流 ...

  5. linux扩展lvm磁盘

    env: centos 6.5 x64 hyper-v虚拟机 这个方法可以在当前运行的系统中扩展root磁盘 详细步骤 之前想创建的一个虚拟机的磁盘空间不够用了,所以想扩容一下磁盘. 正好使用的时候是 ...

  6. 使用自定义 jQuery 插件的一个选项卡Demo

    前几天闲着没事,想着编写一个 jQuery 插件,或许这将是一个美好的开始. 这里是html页面: <!DOCTYPE html> <html lang="en" ...

  7. 『奇葩问题集锦』Cannot find module 'webpack/lib/node/NodeTemplatePlugin'

    第一步:npm config get prefix ,获取输出path“C:\Users\jaxGu\AppData\Roaming\npm”加上"\node_modules"用于 ...

  8. MySQL中EXPLAIN解释命令详解

    MySQL中的explain命令显示了mysql如何使用索引来处理select语句以及连接表.explain显示的信息可以帮助选择更好的索引和写出更优化的查询语句. 1.EXPLAIN的使用方法:在s ...

  9. PERL高效代码摘录 - 数组

    1. 2个数组找不同 ,,,,,,); ,); %seen=(); foreach(@a_hast_g){ ; } @unique=grep($seen{$_},@a_cl_g); } map { $ ...

  10. 第一个CUDA程序

    开始学CUDA 先写一个简单的 #include<iostream>__global__ void add( int a, int b, int *c ) { *c = a + b;}in ...