大话数据结构-排序

文章知识点来至于大话数据结构里边章节知识, 这篇主要介绍各种经典的排序算法以及排序算法的使用。所涉及的算法主要包含冒泡排序、简单选择排序、直接插入排序、希尔排序、堆排序、归并排序、快速排序,并对算法做了优化处理。相关代码源码请查看文章最后。本篇最后的算法描述和流程图以及代码实现是重点,如果对本篇感兴趣一定要通过该部分来巩固数据机构。

1 排序的基本概念和分类

排序定义:假设含有n个记录的序列为{r1, r2,…..,rn},其相应的关键字分别为{k1,k2,…….,kn},需确定1,2,…,n的一种排列p1,p2,p3…..,pn,使其相应的关键字满足kp1<=kp2<=kp3<=…<=kpn(非递减或非递增)关系,即使得序列称为一个按关键字有序的序列{rp1,rp2,rp3,…,rpn},这样的操作就称为排序。

稳定性:假设ki=kj(1<=i<=n,1<=j<=n,i<>j),且在排序前的序列中ri领先于rj(即i<j)。如果排序后ri仍然领先于rj,则称所有的排序方法是稳定的;反之,若可能使得排序后的序列中rj领先于ri ,则称为所有的排序方法是不稳定的。

2 内排序和外排序

         内排序是在排序整个过程中,待排序的所有记录全部放置在内存中。外排序是由于排序的记录个数太多,不能同时放置在内存中,整个过程需要在内外存之间多次交换数据才能进行。

         内部排序性能影响:时间性能、辅助空间、算法的复杂性

3 冒泡排序

         定义:冒泡排序是一种交换排序,他的基本思想是:两两比较相邻记录的关键字,如果反序则交换,直到没有反序的记录为止。

最简单排序实现:

                       

冒泡排序实现:

 

         冒泡排序优化:

 

4 简单选择排序

         定义:简单选择排序法(Simple Selection Sort)就是通过n-i次关键字之间的比较,从n-i+1个记录中选出关键字最小的记录,并和第i(1<=i<=n)个记录交换之。

         代码实现:

 

         复杂度分析:

                   最大的特点就是交换移动数据的次数比较少,时间复杂度和冒泡排序一样O(n2)。但总体性能比冒泡排序算法好。

5 直接插入排序

         定义:直接插入排序的基本操作是将一个记录插入到已经排好序的有序表中,从而得到一个新的、记录数增1的有序表。

         代码实现:

 

                   复杂度分析:只需要一个辅助空间,事件复杂度为O(n2)。

6 希尔排序

         希尔排序的分割策略:将相距某个“增量”的记录组成一个子序列,这样才能保证在子序列内分别进行直接插入排序后得到的结果基本有序而不是局部有序。

         算法实现:

   

         复杂度分析:希尔排序的关键并不是随便分组后自排序,而是将相隔某个“增量”的记录组成一个序列,实现跳跃式的移动,使得排序效率提高。时间复杂度为O(n3/2)。

7 堆排序

堆定义:堆是具有下列性质的二叉树,每个节点的值都大于等或等于其左右孩子节点的值,称为大顶堆;或者每个节点的值都小于或等于其左右孩子节点的值,称为小定堆。

堆排序定义:将待排序的序列构造成一个大顶堆。此时,整个序列的最大值就是堆顶的根结点。将它移走(其实就是将其与堆数组的末尾元素交换,此时未元素就是最大值),然后将剩下的n-1个序列重新构造成一个堆,这样就会得到n个元素中的次小值。如此反复执行,便能得到一个有序序列了。

思路:1、如何由一个无须序列构建成一个堆。2、如果在输出对顶元素后,调整剩余元素称为一个新的堆。

   算法实现:

    

    

         复杂度分析:度排序的事件复杂度为O(nlogn),由于堆排序对原始记录的排序状态不敏感,因此它无论是最好、最坏、平均时间复杂度均为O(nlogn)。这在性能方面远远好于冒泡、简单排序、直接插入的O(n2)。

 

7 归并排序算法

         定义:归并排序算法的原理是假设初始记录含有n个记录,则可以看成是n个有序的子序列,每个子序列的长度为1,然后两两归并,得到[n/2]([x]表示不小于x的最小整数)个长度为2或者1的有序子序列;再两两归并,…,如此重复,直到得到一个长度为n的有序序列为止,这种排序方法称为2路归并排序。

         算法实现:

        

  

   

  

复杂度分析:总的时间复杂度为O(nlogn);空间复杂度O(n+logn)。

8 快速排序

         定义:通过一趟排序将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序的目的

         算法实现:

   

  

     

         算法复杂度分析:时间复杂度为O(logn),空间复杂度为0(logn)。

 

9 总结回顾

        

10 快速排序流程图

11 算法实现

public class QuickSortAlgorithm
    {
        public void QSort(ref int[] array)
        {
            QSort(ref array, 0, array.Length - 1);
        }

        private void QSort(ref int[] array, int low, int high)
        {
            if (low < high)
            {
                var pivot = Partition(ref array, low, high);
                QSort(ref array, low, pivot - 1);
                QSort(ref array, pivot + 1, high);
            }
        }

        private int Partition(ref int[] array, int low, int high)
        {
            int pivotKey = array[low];
            while (low < high)
            {
                while (low < high && array[high] >= pivotKey)
                {
                    high--;
                }
                Swap(array, low, high);
                while (low < high && array[low] <= pivotKey)
                {
                    low++;
                }
                Swap(array, low, high);
            }

            return low;
        }

        private void Swap(int[] array, int low, int high)
        {
            var tempValue = array[low];
            array[low] = array[high];
            array[high] = tempValue;
        }
    }
算法实现

12单元测试

  private static void TestQuickSort()
        {
            var array = new int[] {50, 10, 90, 30, 70, 40, 80, 60, 20};
            var qSort = new QuickSortAlgorithm();
            qSort.QSort(ref array);
            Assert.IsEqual(array[0], 10);
            Assert.IsEqual(array[array.Length - 1], 90);
            Assert.IsEqual(array[4], 50);
        }
单元测试

最后附上源代码下载地址:

http://download.csdn.net/detail/w_wanglei/5689883

posted @ 2013-09-11 14:14  heavi  阅读(2033)  评论(1编辑  收藏  举报