• 常见排序算法的实现


    插入排序:简单地说,就是就将无序序列依次插入到有序序列中。
    算法描述:
    1. 从第一个元素开始,该元素可以认为已经被排序
    2. 取出下一个元素,在已经排序的元素序列中从后向前扫描
    3. 如果该元素(已排序)大于新元素,将该元素移到下一位置
    4. 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
    5. 将新元素插入到该位置后
    6. 重复步骤2~5
    时间复杂度:
    最坏情况;O(n^2);
    平    均:O(n^2);

    /*********** 插入排序 ************/
    void InsertSort(int *p, const int len)
    {
        assert(p != NULL);
    
        int i;
        int j;
        int temp;
    
        for (i = 1; i < len; i++)
        {
            temp = p[i];
            for (j = i-1; j >= 0; j--)
            {
                if (p[i] > temp)
                {
                    p[j+1] = p[j];
                }
                else
                {
                    break;
                }
            }
            p[j+1] = temp;
        }
    }
    


    冒泡排序: 一种简单地排序算法。
    算法描述:
    1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
    2. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这样会使得最后的元素为最大值;
    3. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
    时间复杂度:
    最坏情况;O(n^2);
    平    均:O(n^2);

    /*********** 冒泡排序 ************/
    void BubbleSort(int *p, const int len)
    {
        assert(p != NULL);
    
        int i;
        int j;
        int temp;
    
        for (i = 0; i < len; i++)
        {
            for (j = 0; j < len-i-1; j++)
            {
                if (p[j] > p[j+1])
                {
                    temp = p[j];
                    p[j] = p[j+1];
                    p[j+1] = temp;
                }
            }
        }
    }
    
    /*********** 冒泡排序 ************/
    void BubbleSort(int *p, const int len)
    {
        assert(p != NULL);
    
        int i;
        int j;
        int temp;
    
        for (i = 0; i < len; i++)
        {
            for (j = i+1; j < len; j++)
            {
                if (p[i] > p[j])
                {
                    temp = p[i];
                    p[i] = p[j];
                    p[j] = temp;
                }
            }
        }
    }
    


    选择排序:从未排序列中找到最大(小)元素将其置于合适的位置。
    算法描述:
    1. 在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,
    2. 从剩余未排序元素中继续寻找最小(大)元素,放到已排序序列的末尾。
    3. 重复步骤2,直到所有元素均排序完毕。
    时间复杂度:
    最坏情况;O(n^2);
    平    均:O(n^2);

    /*********** 选择排序 ************/
    void SelectSort(int *p, const int len)
    {
        assert(p != NULL);
    
        int i;
        int j;
        int k;
        int temp;
    
        for (i = 0; i < len-1; i++)
        {
            k = i;
            for (j = i+1; j < len; j++)
            {
                if (p[k] > p[j])
                {
                    k = j;
                }
            }
    
            if (k != i)
            {
                temp = p[i];
                p[i] = p[k];
                p[k] = temp;
            }
        }
    }
    


    快速排序:通过一趟排序将待排记录分隔成独立的两部分,其中以部分记录的关键字比另一部分记录的关键字小,
    则可分别对这两部分记录继续进行排序,以达到整个序列有序。
    算法描述:
    1. 设置两个变量low、high,排序开始的时候:low=0,high=N-1;
    2. 以第一个数组元素作为关键数据,赋值给key,即key=A[0];
    3. 从high开始向前搜索,即由后开始向前搜索(high--),找到第一个小于key的值p[high],将值为key的项与p[high]交换;
    4. 从low开始向后搜索,即由前开始向后搜索(low++),找到第一个大于key的p[low],将值为key的项与p[low]交换;
    5. 重复第3、4、5步,直到low=high; (3,4步中,没找到符合条件的值,即3中p[high]不小于key,4中p[low]不大于key的时候改变low、high的值,使得high=high-1,low=low+1,直至找到为止。找到符合条件的值,进行交换的时候low,high指针位置不变。另外,low==high时令循环结束)。
    时间复杂度:
    最坏情况:O(n^2);
    平    均:O(nlogn);

    /*********** 调整分区 ************/
    int Partition(int *p, const int low, const int high)
    {
        assert(p != NULL);
    
        int i = low;
        int j = high;
        int key = p[low];
    
        while (i < j)
        {
            while (i < j && key <= p[j])
            {
                j--;
            }
            if (i < j)
            {
                p[i++] = p[j];
            }
    
            while (i < j && key > p[i])
            {
                i++;
            }
            if (i < j)
            {
                p[j--] = p[i];
            }
        }
        p[i] = key;
    
        return i;
    }
    
    
    /*********** 快速排序 ************/
    void QuickSort(int *p, const int low, const int high)
    {
        assert(p != NULL);
    
        int pos = Partition(p, low, high);
        if (low < high)
        {
            QuickSort(p, low, pos-1);	// 递归地对关键字前面的序列进行排序
            QuickSort(p, pos+1, high);  // 递归地对关键字后面的序列进行排序
        }
    }
    


    堆排序:是指利用堆这种数据结构所设计的一种排序算法。
    算法思想:
    1. 初始化操作:将R[1..n]构造为“大顶堆”;
    2. 将当前无序区的堆顶记录R[0]和该序列的最后一个记录交换,然后将新的无序区调整为堆(亦称重建堆);
    3. 直到所有元素有序;
    时间复杂度:
    最坏情况;O(nlogn);
    平    均:O(nlogn);

    /*********** 构建大顶堆 ************/
    void AdjustTop(int *p, const int len)
    {
        assert(p != NULL);
    
        int pos = len / 2 - 1;
        int t;
        int temp;
    
        while (pos >= 0)
        {
            if (pos*2+2 == len)	   // 只有自由左子树的情况
            {
                t = p[pos*2+1] > p[pos] ? pos*2+1 : pos;
            }
            else	// 左右子树都存在
            {
                t = p[pos*2+1] > p[pos*2+2] ? pos*2+1 : pos*2+2;
                t = p[t] > p[pos] ? t : pos;
            }
    
            if (t != pos)	// 加此条件判断以减少交换次数
            {
                temp = p[pos];
                p[pos] = p[t];
                p[t] = temp;
            }
    
            pos--;
        }
    }
    
    
    /*********** 堆排序 ************/
    void HeapSort(int *p, const int len)
    {
        assert(p != NULL);
    
        int i;
        int temp;
    	
        for (i = 0; i < len; i++)
        {	
            AdjustTop(p, len-i);	//对剩余元素重新构建“大顶堆”
            temp = p[0];
            p[0] = p[len-i-1];
            p[len-i-1] = temp;
        }
    }
    


    各种内部排序方法的比较:
    1. 就平均时间性能而言,快速排序最佳,其所需时间最少,但快速排序在最坏情况下的性能不如堆排序;
    2. 由于堆排序在最坏情况下的时间复杂度和平均时间复杂度差不多,所以待排序列中元素初始时的顺序对该排序算法没有太大影响。
    2. 从方法的稳定性来看,所有时间复杂度为O(n^2)的简单排序法都是稳定的(包括插入排序、冒泡排序、选择排序)。一般来说,排序过程中的“比较”是在“相邻的两个记录关键字”间进行的排序方法都是稳定的。

  • 相关阅读:
    iOS AutoLayout的用法
    UIPickerView的使用(一)
    UIPickerView的使用(二)
    logging模块
    configparser模块
    hashlib模块
    json & pickle 模块
    对表的操作
    表记录曾删改查
    库、表曾删改查和存储引擎
  • 原文地址:https://www.cnblogs.com/pangblog/p/3295318.html
Copyright © 2020-2023  润新知