您的位置:首页 > 编程语言 > C#

几种常用排序方法的C#实现

2013-08-07 02:07 696 查看
详见:http://student.zjzk.cn/course_ware/data_structure/web/paixu/paixu8.3.1.1.htm

在网上搜罗了一下,各种排序方法的实现:

1:插入排序 a.直接插入排序 b.希尔排序

2:交换排序 a.冒泡排序 b.快速排序

3:选择排序 a.直接选择排序

4:归并排序 a.归并排序

5:分配排序 a.箱排序 b.基数排序

1.a: 直接插入排序

假设待排序的记录存放在数组R[1..n]中。初始时,R[1]自成1个有序区,无序区为R[2..n]。从i=2起直至i=n为止,依次将R[i]插入当前的有序区R[1..i-1]中,生成含n个记录的有序区。每次从无序表中取出第一个元素,把它插入到有序表的合适位置,使有序表仍然有序。

一趟直接插入排序两种方法:

1.简单方法

 首先在当前有序区R[1..i-1]中查找R[i]的正确插入位置k(1≤k≤i-1);然后将R[k..i-1]中的记录均后移一个位置,腾出k位置上的空间插入R[i]。

注意:

 若R[i]的关键字大于等于R[1..i-1]中所有记录的关键字,则R[i]就是插入原位置。

2.改进的方法

  一种查找比较操作和记录移动操作交替地进行的方法。

具体做法:

 将待插入记录R[i]的关键字从右向左依次与有序区中记录R[j](j=i-1,i-2,…,1)的关键字进行比较:

 ① 若R[j]的关键字大于R[i]的关键字,则将R[j]后移一个位置;

②若R[j]的关键字小于或等于R[i]的关键字,则查找过程结束,j+1即为R[i]的插入位置。

 关键字比R[i]的关键字大的记录均已后移,所以j+1的位置已经腾空,只要将R[i]直接插入此位置即可完成一趟直接插入排序

/// <summary>
/// 对顺序表arr中的记录按递增序进行插入排序
/// int[] arr = { 99, 2, 13, 5, 75, 33, 10, 87, 55, 12, 1, 6, 34, 47 };
/// </summary>
/// <param name="arr"></param>
static void InsetSort1(int[] arr)
{
    int i, j, pos;
    for (i = 1; i < arr.Length; i++)  //依次插入arr[1],…,arr[n-1]
    {
        pos = 0;
        // 在有序表中,从右向左扫描,来确定插入项arr[i]的插入位置
        for (j = i - 1; j >= 0; j--) 
        {
            if (arr[i] >= arr[j]) 
            {
                pos = j+1;
                break;
            }
        }
        // 将arr[i]插入到位置j
        if (i == pos)
        {
            continue;
        }
        else
        {
            int temp = arr[i];
            for (j = i-1; j >= pos; j--) 
            {
                arr[j + 1] = arr[j];
            }
            arr[pos] = temp;
        }

    }
}

/// <summary>
/// 对顺序表arr中的记录按递增序进行插入排序
/// int[] arr = { 99, 2, 13, 5, 75, 33, 10, 87, 55, 12, 1, 6, 34, 47 };
/// </summary>
/// <param name="arr"></param>
static void InsetSort2(int[] arr)
{
    int i, j;
    for (i = 1; i < arr.Length; i++) // 依次插入arr[1],…,arr[n-1]
    {
        // 在有序表中,从右向左扫描,若arr[j]的关键字大于arr[i]的关键字,则将arr[j]后移一个位置;
        int temp = arr[i];
        for (j = i - 1; j >= 0; j--)
        {
            if (arr[j] > temp)
            {
                arr[j + 1] = arr[j];
                arr[j] = temp;
            }
        }
    }
}


1.b 希尔排序

希尔排序(Shell Sort)是插入排序的一种。因D.L.Shell于1959年提出而得名。基本思想:

  先取一个小于n的整数d1作为第一个增量,把文件的全部记录分成d1个组。所有距离为dl的倍数的记录放在同一个组中。先在各组内进行直接插人排序;然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量dt=1(dt<dt-l<…<d2<d1),即所有记录放在同一组中进行直接插入排序为止。该方法实质上是一种分组插入方法。

在希尔排序中首先解决的是子序列的选择问题。对于子序列的构成不是简单的分段,而是采取相隔某个增量的数据组成一个序列。一般的选择原则是:用上一个增量的一半作为此次序列的划分增量。首次选择序列长度的一半为增量。

/// <summary>
/// 希尔排序算法的实现
/// </summary>
/// <param name="arr"></param>
static void ShellSort(int[] arr)
{
    int d = arr.Length / 2;    // 设置希尔排序的增量
    int i, j, temp;

    while (d >= 1)
    {
        for (i = d; i < arr.Length; i++ )
        {
            temp = arr[i];
            j = i - d;
            while (j >=0 && arr[j] > temp)
            {
                arr[j + d] = arr[j];
                arr[j + d] = temp;

                j = j - d;
            }                   
        }
        d = d / 2;      //缩小增量

    }
        
}


2.a:冒泡排序

比较相邻的元素。如果第一个比第二个大,就交换他们两个。

对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。

针对所有的元素重复以上的步骤,除了最后一个。

持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

/// <summary>
/// 对顺序表arr中的记录按递增序进行插入排序
///  int[] arr = { 99, 2, 13, 5, 75, 33, 10, 87, 55, 12, 1, 6, 34, 47 };
/// </summary>
/// <param name="arr"></param>
static void BubbleStort(int[] arr)
{
    // arr是待排序的数组,采用自后向前扫描,对arr做冒泡排序
    bool exchangeFlag;     //交换标志
    for (int i = 1; i < arr.Length; i++)    // 最多做n-1趟排序
    {
        exchangeFlag = false;    //本趟排序开始前,交换标志应为假
        for (int j = arr.Length - 1; j >= i; j--)      //对当前无序区arr[i..j]自后向前扫描
        {
            if (arr[j] < arr[j - 1])   //交换记录
            {
                int temp = arr[j];
                arr[j] = arr[j - 1];
                arr[j - 1] = temp;

                exchangeFlag = true; //发生了交换,故将交换标志置为真
            }
        }

        if(!exchangeFlag)
        {
            //本趟排序未发生交换,说明从本趟开始,剩下的arr[i...j]有序的,提前终止算法
            break;
        }
    }

}


2.b 快速排序

快速排序(Quicksort)是对冒泡排序的一种改进。由C. A. R. Hoare在1962年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

步骤:设有一待排序的序列

1.分别设置low、hight指向序列的最左端、最右端;从序列中选一个进行排序(通常选最左端的值low指向的值),存入到tmp;

2.从hight端开始,查找比tmp小的,找到后讲该值放入到low指向的存储位中;同时将hight指向当前查到的值所在的位;

3.从low端开始,查找比tmp大的,找到后将该值放入到hight指向的存储为中,同时low指向当前查到的值所在位;

4.若low位小于hight位,返回2步;否则,将tmp值存入到空出来的low+1指向的位置,退出,返回low所在的位置lposition。

5.以lposition为界,将序列分成两部分,分别对两部分进行排序。

static void QuickSort(int[] arr)
{
    QuickSort(arr, 0, arr.Length - 1);
}

/// <summary>
/// 快速排序算法C#实现
/// </summary>
static void QuickSort(int[] arr, int left, int right)
{
    if (arr == null || left < 0 || left >= right || right >= arr.Length)
    {
        return;
    }
           
    int i = left;
    int j = right;
    // 从数组两端交替地向中间扫描 
    if (left <= right)
    {
        // 设置基准值
        int key = arr[left];
        // 进行扫描的指针i,j;i从左边开始,j从右边开始
        while (i < j)
        {
            // 右
            while (i < j && arr[j] > key)
            {
                j--;
            }
            if (i < j)
            {
                // 比枢纽元素小的移动到左边 
                arr[i] = arr[j];
                i++;
            }

            // 左
            while (i < j && arr[i] < key)
            {
                i++;
            }
            if (i < j)
            {
                // 比枢纽元素大的移动到右边 
                arr[j] = arr[i];
                j--;
            }
        }

        // 枢纽元素移动到正确位置 
        arr[i] = key;
        // 表递归排序 
        QuickSort(arr, left, i - 1); 
        QuickSort(arr, i + 1, right); 
    }

}


3.a 直接选择排序

直接选择排序(Straight Select Sorting) 也是一种简单的排序方法,它的基本思想是:第一次从R[0]~R[n-1]中选取最小值,与R[0]交换,第二次从R[1]~R[n-1]中选取最小值,与R[1]交换,....,

第i次从R[i-1]~R[n-1]中选取最小值,与R[i-1]交换,.....,第n-1次从R[n-2]~R[n-1]中选取最小值,与R[n-2]交换,总共通过n-1次,得到一个按排序码从小到大排列的有序序列.

static void SelectSort(int[] arr)
{
    for (int i = 0; i < arr.Length-1; i++ )
    {
        int minIndex = i;
        for (int j = i + 1; j < arr.Length; j++ )
        {
            if (arr[j] < arr[minIndex])
            {
                minIndex = j;
            }
        }
        if (minIndex != i)
        {
            int temp = arr[i]; 
            arr[i] = arr[minIndex];
            arr[minIndex] = temp;
        }

    }
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: