悟已往之不谏,知来者之可追

第十章、排序问题

第十章、排序

一、各个排序的时间复杂度:

  

二、概念:

  1、稳定排序:若记录序列中有两个或两个以上关键字相等的记录:Ki=kj(i!=j),排序后的记录序列仍然是Ri先于Rj,则称排序方法是稳定的,否则是不稳定的。

        否则则是不稳定排序。

  2、内部排序:待排序的记录书不太多:所有的记录都能存放在内存中进行排序,称为内部排序。

  3、外部排序:待排序列的记录数太多:所有的记录不可能存放在内存中,排序过程中必须在内、外存之间进行数据交换,这样的排序称为外部排序。

三、插入排序:

    1、基本操作:

      将一个记录插入到已排好序的有序表中,从而得到一个新的、记录数增一的有序表。

      其时间复杂度为o(n*n).

    2、代码:

      

#include<cstdio>
#include<iostream>
using namespace std;
int a[100]={}; 
int main(){
    int n=0;
    int b=0;
    while(cin>>a[n++]);
    n=n-1;
//    for(int i=0;i<n;i++){
//        cout<<a[i]<<" ";
//    }
//    cout<<"\n";
    for(int i=1;i<n;i++){
        int key=a[i];
        int j=i-1;
        for(;j>=0&&a[j]>key;j--){
            a[j+1]=a[j];
        }
        a[j+1]=key;
    }
    for(int i=0;i<n;i++){
        cout<<a[i]<<" ";
    }
    cout<<"\n";
} 
//测试用例
//3 65 43 32 2 1 43 54 
View Code

 

 

 

 

 

四、希尔排序:

   1、排序思想:

      利用增量进行排序。

      

                    

                

五、快速排序:

  1、排序思想:通过选定一个参照,将待排序列分为独立的两部分,其中一部分记录的关键字均比另一部分小,再分别对这两部分记录进行下一次排序,已达到整个序列有序。

  2、代码:

    

//归并排序 
#include<iostream>
using namespace std;
int partition(int* a,int p,int r){
    int i=p-1;
    int j=p;
    int key=a[r];
    for(;j<r;j++){
        if(a[j]<=key){
            i=i+1; 
            int temp=a[i];
            a[i]=a[j];
            a[j]=temp;
        }
    }
    a[r]=a[i+1];
    a[i+1]=key;
    return (i+1);
}
void quick_sort(int* a,int p,int r){
    if(p<r){
        int q;
        q=partition(a,p,r);
        quick_sort(a,p,q-1);
        quick_sort(a,q+1,r);
    }
}
int main(){
    int n;
    int a[100]={};
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>a[i];
    } 
    quick_sort(a,0,n-1);
    for(int i=0;i<n;i++)
        cout<<a[i]<<" ";
}

 

、选择排序:

  1、基本操作:

    通过n-i次操作,从n-i+1个记录中选取关键字最小的记录,然后和第i个记录交换。

  2、算法复杂度:

    o(n*n)

七、归并排序:

  1、只将两个或者两个以上的有序序列合并成一个有序序列。若采用现象表,其时间复杂度为o(m+n).

  2、代码:

    

 1 #include<iostream>
 2 using namespace std;
 3 int a[100]={};
 4 #define Max 100000
 5 void merge(int* a,int p,int q,int ri){
 6     int l=q-p+1;
 7     int r=ri-q;
 8     int left[l+1]={};
 9     int right[r+1]={};
10     for(int i=0;i<=l;i++){
11         left[i]=a[i+p];
12     }
13     for(int j=0;j<r;j++){
14         right[j]=a[j+q+1];
15     }
16     left[l]=Max;
17     right[r]=Max;
18     int i=0;
19     int j=0;
20     for(int k=p;k<=ri;k++){
21         if(left[i]<=right[j]){
22             a[k]=left[i++];
23         }else{
24             a[k]=right[j++];
25         }
26     }
27     
28 }
29 void merge_sort(int* a,int p,int r){
30     if(p<r){
31         int q;
32         q=(int)((p+r)/2);
33         //cout<<q;
34         merge_sort(a,p,q);
35         merge_sort(a,q+1,r);
36         merge(a,p,q,r);
37     }    
38 }
39 int main(){
40     int n;
41     cin>>n;
42     for(int i=0;i<n;i++){
43         cin>>a[i];
44     }
45     merge_sort(a,0,n-1);
46     for(int i=0;i<n;i++){
47         cout<<a[i]<<" ";
48     }
49     cout<<"\n";
50 }
View Code

 

 

 

八、冒泡排序:

  1、思想:每次将相邻的两个进行比较,直到每次将最大的冒泡到最底部。(我认为主要需要和选择排序进行区分,选择排序需要每次和n-i+1个数比较,而冒泡排序是和相邻元素比较)。

  2、代码:

    

#include<stdio.h>
int maopao(int *a,int n){
    for(int i=0;i<n;i++){
        for(int j=0;j<n-i-1;j++){
            if(a[j]>a[j+1]){
                int tmp=a[j+1];
                a[j+1]=a[j];
                a[j]=tmp;
            }
        }
    }
}
int main(){
    int i=0;
    int a[100];
    while(scanf("%d",&a[i++])==1);
    i=i-1;
    maopao(a,i);
    for(int j=0;j<i;j++){
        printf("%d ",a[j]);
    }
    printf("\n");
}

 

posted @ 2018-04-08 16:39  monty1  阅读(132)  评论(0编辑  收藏  举报