选择排序

概念

选择排序:从排序的记录中选择出关键字最小的记录,顺序放在已排好的子文件的后面

常用的方法

直接选择法 、 堆排序

直接排序的思想:n 个记录的文件的直接选择排序需要经过n-1次直接排序所得出结果

void SelectSort(int *arr, int len)

{

    int i,j;        // 为循环做准

    int iMin;        // 存储每次最小值

    int temp;        // 作为临时存储值

    for (i=0; i<len-1; i++)        // 进行len-1趟比较即可

    {

        iMin = i;                // 存储每次最小值

        for (j=i+1; j<len; j++)    // 第i次需要与之比较的数据

        {

            if (arr[iMin]>arr[j])

            {

                iMin = j;        // 记录最小值的位置

            }

        }

        temp = arr[i];            // 交换

        arr[i] = arr[iMin];

        arr[iMin] = temp;

    }

}

直接排序的核心:确定待排序的的数据  、确定比较的数据、找出最小值、进行交换

直接排序的算法性能分析

直接选择排序和直接插入排序类似,都分为无序区、有序区、 区别:直接插入排序是将无序区的第一个元素直接插入到有序区;直接选择排序 把最小的元素放到最后

例子

void Selectsort(int a[], int n)
{
    int i, j, nMinIndex;
    for (i = 0; i < n; i++)
    {
        nMinIndex = i; //找最小元素的位置
        for (j = i + 1; j < n; j++)
            if (a[j] < a[nMinIndex])
                nMinIndex = j;
 
        Swap(a[i], a[nMinIndex]); //将这个元素放到无序区的开头
    }
}

 堆排序

堆排序类似于一个二叉树除了最底层之外其它层都是满的

二叉堆 分为 最小堆和最大堆

最大堆:每个父节点的元素大于等于 孩子的节点

实现

void AdjustMaxHeap(int a[], int i, int n)  
{  
    int j, temp;  
    temp = a[i];        // 保存第i个结点值
    j = 2 * i + 1;        // 第i个结点的左孩子
    while (j < n)  
    {  
        if (j + 1 < n && a[j + 1] > a[j])    // 在左右孩子中找最大的  
            j++;                // 如果右孩子大,j就变成右孩子序号
        if (a[j] <= temp)            // 如果左右孩子的值都不大于父结点,就终止
            break;  
        a[i] = a[j];            // 把较大的子结点往上移动,替换它的父结点  
        i = j;                // 为下次循环做准备
        j = 2 * i + 1;  
    }  
    a[i] = temp;                          // 保存父结点的值,此时i是j的值,表示孩子的值

}

功能:建立初始堆(最大堆)
思路:
1、要想将初始文件R[1..n]调整为一个大根堆,就必须将它
所对应的完全二叉树中以每一结点为根的子树都调整为堆。
2、显然只有一个结点的树是堆,而在完全二叉树中,所有序号i>[n/2]([]向下取整)的
结点都是叶子,因此以这些结点为根的子树均已是堆。
3、我们只需依次将以序号为[n/2],[n/2]-1,...1的结点作为根的子树都调整为堆即可。
4、由于c语言中数组下标从0开始,因此,第3点的序号改为[n/2]-1,[n/2]-2,...0

void MakeMaxHeap(int a[], int n)  

{  

    for (int i = n / 2 - 1; i >= 0; i--)    // 根结点序号

        AdjustMaxHeap(a, i, n);        // 为每个根结点调整,保存最大堆性质

}
    1、建立初始堆

    2、每一趟最后一个数都与a[0]交换,并重新调整堆,

        使其保持堆的特性。

*/
void MaxHeapSort(int a[], int n)  
{  

    MakeMaxHeap(a,n);        // 建立初始堆

    for (int i = n - 1; i >= 1; i--)    // 对当前无序区a[1..i]进行堆排序,共做n-1趟

    {  

        int temp = a[i];    // 将堆顶和堆中最后一个记录交换

        a[i] = a[0];

        a[0] = temp;        

        AdjustMaxHeap(a, 0, i);    // 将a[0..i]重新调整为最大堆,仅有a[0]可能违反堆性质

    }  

}  

 

堆排序的算法性能分析
堆排序是不稳定,但是它的平均时间复杂度和最差情况时间复杂度都是O(nlogn)
 
posted @ 2019-06-26 14:30  君莫笑~~  阅读(208)  评论(0编辑  收藏  举报