各种排序算法大集合

计算机程序就是数据结构加算法。可见算法在计算机世界的重要性,本文所述的算法是指基础通用的查找和排序算法,其是其他更复杂算法的基础,总结在此以备将来查阅。

排序算法

排序算法又分为好多种

  1. 简单排序(Simple sorts)
    1.1 插入排序(Insertion sort)
    1.2 选择排序(Selection sort)
  2. 有效排序(Efficient sorts )
    2.1 Merge sort (归并排序)
    2.2 Heapsort (堆排序)
    2.3 Quicksort (快速排序)
  3. 冒泡排序及其变种(Bubble sort and variants )
    3.1 Bubble sort (冒泡排序)
    3.2 Shell sort (希尔排序)
    3.3 Comb sort (梳排序)
  4. 分布排序(Distribution sort )
    4.1 Counting sort(计数排序)
    4.2 Bucket sort(桶排序)
    4.3 Radix sort(基数排序)

简单排序

  • 插入排序

    算法:相当与将要排序的数组中的元素一个一个取出,插入新的空数组中,插的过程中进行排序
    平均时间复杂度:n*n
    最好时间复杂度:n

    C#代码示例

    public static int InsertionSort(int[] numArray)  
    {  
        for (int i = 1; i < numArray.Length; i++)  
        {  
            int j = i;  
            while (j > 0)  
            {  
                if (numArray[j - 1] > numArray[j])  
                {  
                    int temp = numArray[j - 1];  
                    numArray[j - 1] = numArray[j];  
                    numArray[j] = temp;  
                    j--;  
                }  
                else  
                    break;  
            }  
        }  
        return 0;  
    }
  • 选择排序

    算法:将一个list分为两部分,一部分为排序完成的,另一部分为无序的,在无序中选择最小的那个与有序集合中下一个位 置的数字交换 。永远使用插入排序代替选择排序。
    时间复杂度:n*n

    C#代码示例

  public static void SelectionSort(int[] numArray)  
  {  
      //最小元素的下标  
      int min;  
      for (int i = 0; i < numArray.Length - 1; i++)  
      {  
          //假设最小元素为第一个,开始比较判断  
          min = i;  
          //找到最小元素的下标  
          for (int j = i + 1; j < numArray.Length; j++)  
          {  
              if (numArray[j] < numArray[min])  
              {  
                  min = j;  
              }  
          }  

          int temp = numArray[i];  
          numArray[i] = numArray[min];  
          numArray[min] = temp;  
      }  
  }

有效排序

  • 归并排序
    算法: 将要排序的数组不断的分成两个数组,直到每个数组只有一个元素,然后合并相邻数组

    C#代码示例

    //将有序数组a[]和b[]合并到c[]中    
    private void mergeArray(int[] a, int n, int[] b, int m, int[] c)  
    {  
        int i, j, k;  

        i = j = k = 0;  
        while (i < n && j < m)  
        {  
            if (a[i] < b[j])  
                c[k++] = a[i++];  
            else  
                c[k++] = b[j++];  
        }  

        while (i < n)  
            c[k++] = a[i++];  

        while (j < m)  
            c[k++] = b[j++];  
    }  
    //将有二个有序数列numbers[first...mid]和numbers[mid...last]合并。   
    private static void mainMerge(int[] numbers, int first, int mid, int last, int[] temp)  
    {  
        //两个数组的开始下标  
        int i = first, j = mid + 1;  
        //两个数组的结束下标  
        int m = mid, n = last;  
        int k = 0;  

        while ((i <= m) && (j <= n))  
        {  
            if (numbers[i] <= numbers[j])  
                temp[k++] = numbers[i++];  
            else  
                temp[k++] = numbers[j++];  
        }  

        while (i <= m)  
            temp[k++] = numbers[i++];  

        while (j <= n)  
            temp[k++] = numbers[j++];  

        for (i = 0; i < k; i++)  
        {  
            numbers[first + i] = temp[i];  
        }  
    }  
    public static void SortMerge(int[] numbers, int left, int right, int[] temp)  
    {  
        int mid;  
        if (right > left)  
        {  
            mid = (right + left) / 2;  
            SortMerge(numbers, left, mid, temp);  
            SortMerge(numbers, (mid + 1), right, temp);  

            mainMerge(numbers, left, mid, right, temp);  
        }  
    }  
  • 堆排序

    C#代码示例

    //  新加入i结点  其父结点为(i - 1) / 2    
    private void MinHeapFixup(int[] a, int i)    
    {    
        int j, temp;    

        temp = a[i];    
        j = (i - 1) / 2; //父结点    
        //调整顺序  
        while (j >= 0 && i != 0)    
        {    
            //因为操纵的是最小堆,所以从插入节点的父节点开始到根节点是有序的,从大到小  
            //如何其父节点大于它,说明已经是有序的了,不需要在调整  
            if (a[j] <= temp)    
                break;    

            a[i] = a[j];     //把较大的子结点往下移动,替换它的子结点    
            i = j;    
            j = (i - 1) / 2;    
        }    
        a[i] = temp;    
    }    
    //在最小堆中加入新的数据nNum    
    private void MinHeapAddNumber(int[] a, int n, int nNum)    
    {    
        a[n] = nNum;    
        MinHeapFixup(a, n);    
    }   
    //删除节点  
    //从i节点开始调整,n为节点总数 从0开始计算 i节点的子节点为 2*i+1, 2*i+2    
    private static void MinHeapFixdown(int[] a, int i, int n)    
    {    
        int j, temp;    

        temp = a[i];    
        j = 2 * i + 1;    
        while (j < n)    
        {    
            if (j + 1 < n && a[j + 1] < a[j]) //在左右孩子中找最小的    
                j++;    

            if (a[j] >= temp)    
                break;    

            a[i] = a[j];     //把较小的子结点往上移动,替换它的父结点    
            i = j;    
            j = 2 * i + 1;    
        }    
        a[i] = temp;    
    }    
    //在最小堆中删除数    
    void MinHeapDeleteNumber(int []a, int n)    
    {  
        swap(a[0], a[n - 1]);  
        MinHeapFixdown(a, 0, n - 1);    
    }  
    //建立最小堆    
    public static void MakeMinHeap(int[] a, int n)    
    {    
        for (int i = n / 2 - 1; i >= 0; i--)    
            MinHeapFixdown(a, i, n);    
    }    
    public static void MinheapsortTodescendarray(int[] a, int n)    
    {  
        for (int i = n / 2 - 1; i >= 0; i--)  
            MinHeapFixdown(a, i, n);    
        for (int i = n - 1; i >= 1; i--)    
        {    
            swap(a[i], a[0]);  
            MinHeapFixdown(a, 0, i);    
        }    
    }  
    private static void swap(int a, int b)  
    {  
        int temp = a;  
        a = b;  
        b = temp;  
    } 
  • 快速排序
    算法:分而制造之,取一元素,一般为中间元素,将小于此元素的元素放于前面,大于的放于后面对前后两部分再采取同
    样的方法迭代 。
    时间复杂度:nlgn

C#代码示例

public static void QuickSort(IComparable[] elements, int left, int right)  
    {  
        int i = left, j = right;  
        IComparable pivot = elements[(left + right) / 2];  

        while (i <= j)  
        {  
            while (elements[i].CompareTo(pivot) < 0)  
            {  
                i++;  
            }  

            while (elements[j].CompareTo(pivot) > 0)  
            {  
                j--;  
            }  

            if (i <= j)  
            {  
                // Swap  
                IComparable tmp = elements[i];  
                elements[i] = elements[j];  
                elements[j] = tmp;  

                i++;  
                j--;  
            }  
        }  

        // Recursive calls  
        if (left < j)  
        {  
            QuickSort(elements, left, j);  
        }  

        if (i < right)  
        {  
            QuickSort(elements, i, right);  
        }  
    }  

冒泡排序及其变种

  • 冒泡排序
    算法:从小到达排列实现:将相邻的两个值比较,如果此值较小则交换位置,当以一次冒泡后,最小值已经位于最上面了。余下的以此类推。效率低下,适合教学,实际中不要使用。

C#代码示例

    public static void BubbleSort(int[] numArray)  
    {  
        for (int i = 0; i < numArray.Length; i++)  
        {  
            for (int j = 1; j < numArray.Length-i; j++)  
            {  
                if (numArray[j-1]>numArray[j])  
                {  
                    int temp = numArray[j - 1];  
                    numArray[j - 1] = numArray[j];  
                    numArray[j] = temp;  
                }  
            }  
        }  
    }
  • 希尔排序
    算法:分组插入排序,又叫缩小增量排序
    该方法的基本思想是:先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。因为直接插入排序在元素基本有序的情况下(接近最好情况), 效率是很高的。

    C#代码示例

    public static void ShellSort(int[] numArray)  
    {  
        for (int gap = numArray.Length/2; gap >0; gap/=2)  
        {  
            for (int i = 0; i < gap; i++)  
            {  
                for (int j = i+gap; j < numArray.Length; j+=gap)  
                {  
                    if (numArray[j]<numArray[j-gap])  
                    {  
                        int temp = numArray[j];  
                        int k = j - gap;  
                        while (k>=0&&numArray[k]>temp)  
                        {  
                            numArray[k + gap] = numArray[k];  
                            k -= gap;  
                        }  
                        numArray[k + gap] = temp;  
                    }  
                }  
            }  
        }  
    }  
    public static void ShellSortAdvaced(int[] numArray)   
    {    
        int j, gap;  

        for (gap = numArray.Length / 2; gap > 0; gap /= 2)  
            for (j = gap; j < numArray.Length; j++)//从数组第gap个元素开始    
                if (numArray[j] < numArray[j - gap])//每个元素与自己组内的数据进行直接插入排序    
                {  
                    int temp = numArray[j];    
                    int k = j - gap;  
                    while (k >= 0 && numArray[k] > temp)    
                    {  
                        numArray[k + gap] = numArray[k];    
                        k -= gap;    
                    }  
                    numArray[k + gap] = temp;    
                }    
    }
  • 梳排序
    算法:将整个待排序列分成若干组,每个组进行冒泡排序

C#代码示例

public static int[] CombSort(int[] numArray)  
    {  
        double gap = numArray.Length;  
        bool swaps = true;  
        while (gap > 1 || swaps)  
        {  
            gap /= 1.247330950103979;  
            if (gap < 1) { gap = 1; }  
            int i = 0;  
            swaps = false;  
            while (i + gap < numArray.Length)  
            {  
                int igap = i + (int)gap;  
                if (numArray[i] > numArray[igap])  
                {  
                    int swap = numArray[i];  
                    numArray[i] = numArray[igap];  
                    numArray[igap] = swap;  
                    swaps = true;  
                }  
                i++;  
            }  
        }  
        return numArray;  
    }  

分布排序

  • 计数排序
    算法:是一种稳定的排序算法。计数排序使用一个额外的数组C,其中第i个元素是待排序数组A中值等于i的元素的个数, 然后根据数组C来将A中的元素排到正确的位置。

C#代码示例

public static int[] CountingSort(int []numArray)  
    {   
        int []b = new int[numArray.Length];    
        int max = numArray[0], min = numArray[0];    
        foreach(var i in numArray)  
        {    
            if(i > max)  
            {    
                max = i;    
            }    
            if(i < min)  
            {    
                min = i;    
            }    
        }    
        //这里k的大小是要排序的数组中,元素大小的极值差+1    
        int k = max - min + 1;  
        int[] c = new int[k];    
        for(int i = 0; i < numArray.Length; ++i)  
        {    
            c[numArray[i]-min] += 1;//优化过的地方,减小了数组c的大小    
        }  
        for (int i = 1; i < c.Length; ++i)  
        {    
            c[i] = c[i] + c[i-1];    
        }  
        for (int i = numArray.Length - 1; i >= 0; --i)  
        {    
            b[--c[numArray[i]-min]] = numArray[i];//按存取的方式取出c的元素    
        }  

        return b;  
    }  

有时间再完善相关算法的解释。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ShuSheng007

亲爱的猿猿,难道你又要白嫖?

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值