zoukankan      html  css  js  c++  java
  • 排序 O(nlogn)

    1.

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

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #define MAX 111111
     5 #define LEFT(i) (i << 1)
     6 #define RIGHT(i) (i << 1|1)
     7 using namespace std; 
     8 int a[MAX], Heap_Size, a_Length; 
     9 void Max_Heapify(int i){
    10     int largest, l, r; 
    11     l = LEFT(i); 
    12     r = RIGHT(i); 
    13     if(l <= Heap_Size && a[l] > a[i]) largest = l; 
    14     else largest = i; 
    15     if(r <= Heap_Size && a[r] > a[largest]) largest = r; 
    16     if(largest != i){
    17         int temp = a[i]; 
    18         a[i] = a[largest]; 
    19         a[largest] = temp; 
    20         Max_Heapify(largest); 
    21     }
    22     return; 
    23 }
    24 void Build_Heap(){
    25     for(int i = a_Length/2; i >= 1; i --)
    26         Max_Heapify(i); 
    27     return; 
    28 }
    29 void Heap_Sort(){
    30     Build_Heap(); 
    31     for(int i = a_Length; i >= 2; i --){
    32         int temp = a[1]; 
    33         a[1] = a[i]; 
    34         a[i] = temp; 
    35         Heap_Size--; 
    36         Max_Heapify(1); 
    37     }
    38     return ; 
    39 }
    40 int main(){
    41     freopen("data.cpp", "r", stdin); 
    42     freopen("out.cpp", "w", stdout); 
    43     while(~scanf("%d", &a_Length)){
    44         Heap_Size = a_Length; 
    45         for(int i = 1; i <= a_Length; i ++) scanf("%d", a+i); 
    46         Heap_Sort(); 
    47         printf("Length = %d
    ", a_Length); 
    48         for(int i = 1; i < a_Length; i ++) printf("%d ", a[i]); 
    49         printf("%d
    
    
    ", a[a_Length]); 
    50     }
    51     return 0; 
    52 }

    2.

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

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstdlib>
     4 #include<cstring>
     5 #define MAX 111111
     6 using namespace std; 
     7 int a[MAX], a_length; 
     8 int Rand_Partition(int p, int r){
     9     int x = a[r], i = p-1; 
    10     for(int j = p; j < r; j ++){
    11         if(a[j] <= x){
    12             i ++; 
    13             int temp = a[i]; 
    14             a[i] = a[j]; 
    15             a[j] = temp; 
    16         }
    17     }
    18     a[r] = a[i+1]; 
    19     a[i+1] = x; 
    20     return i+1; 
    21 }
    22 void Qucik_Sort(int p, int r){
    23     if(p < r){                //与调用Rand_Partition()函数效果一样;
    24         int i = p-1; 
    25         for(int j = p; j < r; j ++){
    26             if(a[j] <= a[r]){
    27                 i ++; 
    28                 swap(a[i], a[j]); 
    29             }
    30         }
    31         swap(a[r], a[i+1]); 
    32         int q = i+1;             //end;
    33         /* int q = Rand_Partition(p, r); */  
    34         Qucik_Sort(p, q-1); 
    35         Qucik_Sort(q+1, r); 
    36     }
    37 }
    38 int main(){
    39     freopen("data.cpp", "r", stdin); 
    40     freopen("Quick_sort_out.cpp", "w", stdout); 
    41     while(~scanf("%d", &a_length)){
    42         printf("Length = %d
    ", a_length); 
    43         for(int i = 0; i < a_length; i ++) scanf("%d", a+i); 
    44         Qucik_Sort(0, a_length-1); 
    45         for(int i = 0; i < a_length-1; i ++) printf("%d ", a[i]); 
    46         printf("%d
    
    
    ", a[a_length-1]); 
    47     }
    48     return 0; 
    49 }

    3.

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

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

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

     1 #include<stdio.h>
     2 #include<string.h>
     3 int a[1000005]; 
     4 int l[100005]; 
     5 int r[100005]; 
     6 void merge(int p, int mid, int q)
     7 {
     8     int nl = mid - p + 1; 
     9     int nr = q - mid; 
    10     int i, j, k; 
    11     for(i = 0; i < nl; i ++)
    12         l[i] = a[p+i]; 
    13     for(i = 1; i <= nr; i ++)
    14         r[i - 1] = a[mid+i]; 
    15     l[nl] = 1 << 30; 
    16     r[nr] = 1 << 30; 
    17     i = 0; 
    18     j = 0; 
    19     for(k = p; k <= q; k ++)
    20     {
    21         if(l[i] <= r[j])
    22             a[k] = l[i++]; 
    23         else
    24             a[k] = r[j++]; 
    25     }
    26 }
    27 
    28 void merge_sort(int l, int r)
    29 {
    30     if(l < r)
    31     {
    32         int mid = (l + r) >> 1; 
    33         merge_sort(l, mid); 
    34         merge_sort(mid + 1, r); 
    35         merge(l, mid, r); 
    36     }
    37 }
    38 
    39 int main(int argc, char const *argv[]) 
    40 {
    41     int n, i; 
    42     freopen("data.cpp", "r", stdin); 
    43     freopen("Merge_out.cpp", "w", stdout); 
    44     while(~scanf("%d", &n))
    45     {
    46         printf("Length = %d
    ", n); 
    47         for(i = 0; i < n; i ++)
    48             scanf("%d", &a[i]); 
    49         merge_sort(0, n-1); 
    50         for(i = 0; i < n-1; i ++)
    51             printf("%d ",a[i]);
    52         printf("%d
    
    
    ", a[i]); 
    53     }
    54     return 0; 
    55 }

     4.

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

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<stack>
     5 using namespace std; 
     6 typedef struct Node{
     7     int key; 
     8     Node *left; 
     9     Node *right; 
    10     Node(){
    11         left = NULL; 
    12         right = NULL; 
    13     }
    14 }Node; 
    15 Node *root; 
    16 stack<Node*>s; 
    17 void Insert(int key){
    18     Node *tmp = new Node(); 
    19     tmp->key = key; 
    20     Node *ff = root;
    21     Node *flag = NULL; 
    22     while(ff){
    23         flag = ff; 
    24         if(key <= ff->key) ff = ff->left; 
    25         else ff = ff->right; 
    26     }
    27     if(flag == NULL){
    28         root = new Node(); 
    29         root->key = key; 
    30         return; 
    31     }
    32     if(flag->key >= key) flag->left = tmp; 
    33     else flag->right = tmp; 
    34 }
    35 
    36 void Visist_Treee_1(Node *tmp){
    37     if(tmp){
    38         Visist_Treee_1(tmp->left); 
    39         printf("%d ", tmp->key); 
    40         Visist_Treee_1(tmp->right); 
    41     }
    42 }
    43 
    44 /* void Visist_Treee_2(Node *tmp){ */
    45 /*     while(!s.empty()) s.pop(); */ 
    46 /*     s.push(tmp); */ 
    47 /*     while(!s.empty()){ */
    48 /*         Node *p = s.top(); */ 
    49 /*         s.pop(); */ 
    50 /*         while(p->left) s.push(p), p = p->left; */ 
    51 /*         Node *q = s.top(); */ 
    52 /*         s.pop(); */ 
    53 /*         printf("%d ", q->key); */ 
    54 /*         if(q->right) s.push(q); */ 
    55 /*     } */
    56 /* } */
    57 
    58 int main(){
    59     int n, temp; 
    60     freopen("data.cpp", "r", stdin); 
    61     freopen("Binary_Tree_out.cpp", "w", stdout); 
    62     while(~scanf("%d", &n)){
    63         root = NULL; 
    64         printf("Length = %d
    ", n); 
    65         for(int i = 0; i < n; i ++){
    66             scanf("%d", &temp); 
    67             Insert(temp); 
    68         }
    69         Visist_Treee_1(root); 
    70         printf("
    
    
    "); 
    71         /* Visist_Treee_2(root); */ 
    72     }
    73 }
  • 相关阅读:
    jquery下拉菜单打开的同时,同行右边的图标变化
    echarts引入及应用
    好用又美观的时间控件
    C#不支持此安全协议
    python re模块中的函数
    python中的收集参数
    python常用操作符
    python 字符串中常用的内置函数
    VS2012停止工作解决办法
    Jqurey图片放大镜插件
  • 原文地址:https://www.cnblogs.com/anhuizhiye/p/3641925.html
Copyright © 2011-2022 走看看