zoukankan      html  css  js  c++  java
  • 算法基础===》==》=》排序(内部排)

    一些最基本的排序算法:

    插入排序
    交换排序
    选择排序
    @ 插入排序:

    1-直接插入排序:

    从前端插入
    从后端插入
    2-希尔(Shell)排序

    1-直接插入排序:

    从前端插入:
    int arr[]={999,1,2,5,8,4,3,9,7};//"999"是一个容储器(arr[0]是一个监视哨),不参与排序。
    void InsertSort(int n)
    {
    int i,j;
    for(i=2;i<=n;i++)//进行n-1次排序
    {
    arr[0]=arr[i];//设置监视哨---减少扫描量,提高效率。
    j=i-1;//j代表有序序列的最后一个元素
    while(arr[0]<arr[j])
    {
    arr[j+1]=arr[j];//记录后移
    j--;
    }
    arr[j+1]=arr[0];//把存放在arr[0]中的原记录插入到正确位置
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    从后端插入:
    int arr[]={0,1,2,5,8,4,3,9,7,999};//"999"是一个容储器(arr[n+1]是一个监视哨),"0"是填补i=0的空白位置,"999"与"0"均不参与排序。
    void InsertSort(int n)//从第n-1个元素开始向它前面插入,直到第一个元素插入为止。
    {
    int i,j;
    for(i=n-1;i>=1;i--)//进行n-1次排序
    {
    arr[n+1]=arr[i];//设置监视哨
    j=i+1;//j代表有序序列的最后一个元素
    while(arr[n+1]>arr[j])
    {
    arr[j-1]=arr[j];//记录前移
    j++;
    }
    arr[j-1]=arr[n+1];//把存放在arr[n+1]中的原记录插入到正确位置
    }
    }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    2-希尔(Shell)排序==>直接插入排序的改进版

    void InsertSort(int n)
    {
    int i,j,d;
    for(d=n/2;d>=1;d=d/2)//进行n-1次排序
    {
    for(i=d+1;i<=n;i++)
    {
    arr[0]=arr[i];//设置监视哨
    j=i-d;//前后位置的增量为d,而不是1
    while(j>0&&arr[0]<arr[j])
    {
    arr[j+d]=arr[j];//记录后移,查找插入位置
    j=j-d;
    }
    arr[j+d]=arr[0];//插入
    }
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    ------》源代码:

    #include<iostream>
    using namespace std;

    //1.数组的初始化:
    int arr[]={999,1,2,5,8,4,3,9,7};//"999"是一个容储器(arr[0]是一个监视哨),不参与排序。

    //2.希尔排序:
    void InsertSort(int n)
    {
    int i,j,d;
    for(d=n/2;d>=1;d=d/2)//进行n-1次排序
    {
    for(i=d+1;i<=n;i++)
    {
    arr[0]=arr[i];//设置监视哨
    j=i-d;//前后位置的增量为d,而不是1
    while(j>0&&arr[0]<arr[j])
    {
    arr[j+d]=arr[j];//记录后移,查找插入位置
    j=j-d;
    }
    arr[j+d]=arr[0];//插入
    }
    }
    }

    void Show_arr(int n)
    {
    int i;
    for(i=1;i<=n;i++)
    cout<<arr[i]<<' ';
    cout<<endl;
    }

    void main()
    {
    InsertSort(8);
    Show_arr(8);
    }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    直接插入排序的算法的时间复杂度为O(n^2),直接插入排序是一种稳定的排序方法。而shell_sort的算法的时间复杂度为O(n* log2^n)~ O(n ^2) 大略为O(n^(3/2)),shell_sort不是一种稳定的排序方法

    @交换排序:

    冒泡排序
    快速排序
    1- 冒泡排序:

    void Bubble_Sort(int *a,int n)
    {
    int i, j, t;
    for(i=0;i<n-1;i++)
    {
    for(j=0;j<n-i-1;j++)
    if(a[j]>a[j+1])
    {
    t=a[j];
    a[j]=a[j+1];
    a[j+1]=t;
    }
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    2-快速排序:

    void Quick_Sort(int low,int high)
    {
    if(low>=high)
    return ;
    int i=low,j=high;//避免引起歧义
    arr[0]=arr[low];
    while(i<j)
    {
    while(i<j&&arr[0]<=arr[j])//"i<j"绝对不能省,此处与外循环的含义不同
    j--;
    arr[i]=arr[j];
    while(i<j&&arr[i]<=arr[0])
    i++;
    arr[j]=arr[i];
    }
    arr[i]=arr[0];
    Quick_Sort(low,i-1);
    Quick_Sort(i+1,high);
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    ------》源代码:

    #include<iostream>
    using namespace std;

    //1.数组的初始化:
    int arr[]={0,1,2,5,8,4,3,9,7};

    //2.快速排序:一个形象的比喻-》“选取一个中间点,两边互相扔石头”
    void Quick_Sort(int low,int high)
    {
    if(low>=high)
    return ;
    int i=low,j=high;//避免引起歧义
    arr[0]=arr[low];
    while(i<j)
    {
    while(i<j&&arr[0]<=arr[j])//"i<j"绝对不能省,此处与外循环的含义不同
    j--;
    arr[i]=arr[j];
    while(i<j&&arr[i]<=arr[0])
    i++;
    arr[j]=arr[i];
    }
    arr[i]=arr[0];
    Quick_Sort(low,i-1);//这里采用递归来化简算法的难度
    Quick_Sort(i+1,high);
    }
    void Show_arr(int n)
    {
    int i;
    for(i=1;i<=n;i++)
    cout<<arr[i]<<' ';
    cout<<endl;
    }

    void main()
    {
    Quick_Sort(1,8);
    Show_arr(8);
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    冒泡排序的算法的时间复杂度为O(n^2),是一种稳定的排序方法。
    快速排序的算法的时间复杂度为O(n* log2^n)~ O(n ^2),不是一种稳定的排序方法。

    @选择排序:

    直接选择排序
    堆排序
    直接选择排序:

    void Sort(int *a,int len)
    {
    int i,j,min,t;
    for(i=0;i<len-1;i++)
    {
    for(min=i,j=i+1;j<len;j++)
    if(a[min]>a[j])
    {
    min=j;
    }
    if(min!=i)
    {
    t=a[i];
    a[i]=a[min];
    a[min]=t;
    }
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    ------》源代码:

    #include<iostream>
    using namespace std;

    //1.数组的初始化:
    int arr[]={1,2,5,8,4,3,9,7};

    //2.选择排序:
    void Sort(int *a,int len)
    {
    int i,j,min,t;
    for(i=0;i<len-1;i++)
    {
    for(min=i,j=i+1;j<len;j++)
    if(a[min]>a[j])
    {
    min=j;
    }
    if(min!=i)
    {
    t=a[i];
    a[i]=a[min];
    a[min]=t;
    }
    }
    }
    void Show_arr(int n)
    {
    int i;
    for(i=0;i<n;i++)
    cout<<arr[i]<<' ';
    cout<<endl;
    }

    void main()
    {
    Sort(arr,8);
    Show_arr(8);
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    堆排序:==>选择排序的改进版
    *什么是堆?—
    堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的数值或索引总是小于(或者大于)它的父节点。
    堆排序的生成及其排序原理:

    堆排序的实现:

    void Adjust(int i,int n)//i代表待调整元素的下标,n代表最后一元素的下标。
    {
    int j;
    arr[0]=arr[i];
    while(i<n&&2*i<=n)
    {
    j=2*i;//j为i左孩子下标
    if(j<n&&arr[j]>arr[j+1])
    j++;//j指向较小的孩子
    if(arr[0]>arr[j])
    {
    arr[i]=arr[j];
    i=j;
    }
    else
    break;
    }
    arr[i]=arr[0];
    }
    void Build_Heap(int n)
    {
    int i;
    for(i=n/2;i>0;i--)
    Adjust(i,n);
    }
    void Show_arr(int n)
    {
    int i;
    for(i=1;i<=n;i++)
    cout<<arr[i]<<' ';
    cout<<endl;
    }
    void Heap_Sort(int n)
    {
    int i,t;
    Build_Heap(n);
    cout<<"初始堆积树:"<<endl;
    Show_arr(8);
    cout<<endl;
    for(i=n;i>1;i--)
    {
    t=arr[1];
    arr[1]=arr[i];
    arr[i]=t;
    cout<<endl<<"第 "<<n-i+1<<"趟:"<<endl;
    Show_arr(8);
    Adjust(1,i-1);
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    ------》源代码:

    #include<iostream>
    using namespace std;

    //1.数组的初始化:
    int arr[]={0,1,2,5,8,4,3,9,7};

    /*2.堆积树的调整过程:
    从二叉树的叶子节点处往上逐一比较来建立最大堆积树:*/
    void Adjust(int i,int n)//i代表待调整元素的下标,n代表最后一元素的下标。
    {
    int j;
    arr[0]=arr[i];
    while(i<n&&2*i<=n)
    {
    j=2*i;//j为i左孩子下标
    if(j<n&&arr[j]>arr[j+1])
    j++;//j指向较小的孩子
    if(arr[0]>arr[j])
    {
    arr[i]=arr[j];
    i=j;
    }
    else
    break;
    }
    arr[i]=arr[0];
    }

    //3.堆积树的建立:
    void Build_Heap(int n)
    {
    int i;
    for(i=n/2;i>0;i--)
    Adjust(i,n);
    }

    //显示:
    void Show_arr(int n)
    {
    int i;
    for(i=1;i<=n;i++)
    cout<<arr[i]<<' ';
    cout<<endl;
    }

    //4.堆积排序:
    void Heap_Sort(int n)
    {
    int i,t;
    Build_Heap(n);
    cout<<"初始堆积树:"<<endl;
    Show_arr(8);
    cout<<endl;
    for(i=n;i>1;i--)
    {
    t=arr[1];
    arr[1]=arr[i];
    arr[i]=t;
    cout<<endl<<"第 "<<n-i+1<<"趟:"<<endl;
    Show_arr(8);
    Adjust(1,i-1);
    }
    }
    void main(http://www.my516.com)
    {
    Show_arr(8);
    cout<<endl;
    Heap_Sort(8);
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    直接选择排序的算法的时间复杂度为O(n^2),由于直接选择排序交换次数少,当记录占用的字节数较多时,通常比直接插入排序的执行速度要快一些。但它却并不是一种稳定的排序方法,综合来看其性价比 较低.
    堆排序方法对记录数较小的排序效果并不理想,但对于n较大的文件很有意义,因为其运行时间主要建立在初始建堆和反复调整堆上。
    建堆的时间复杂度与堆所对应的完全二叉树的深度的数量级log2^n 有关,而调用数量级为n,所以整个堆排序的时间复杂度为O(n* log2^n)。在空间复杂度方面,堆排序只需要一个辅助空间,为O(1)。此外,堆排序并不是稳定的排序哦。

    *ps:在算法的设计中排序的方法有很多种,但具体情况还需要具体分析,在情景中应当采取最合适的排序算法。
    ---------------------

  • 相关阅读:
    布尔值数据类型
    数据类型
    while循环。for循环
    对于元素类型为集合的List进行排序
    进程和线程之由来
    ExecutorService的关闭
    Java并发编程:CountDownLatch、CyclicBarrier和Semaphore
    什么是设计模式
    java多线程的原子性
    OutputStream的flush()方法
  • 原文地址:https://www.cnblogs.com/ly570/p/11075964.html
Copyright © 2011-2022 走看看