数据结构(排序)

来源:互联网 发布:打击网络犯罪宣传资料 编辑:程序博客网 时间:2024/06/03 17:08

1>排序是把一个记录(在排序中把数据元素称为记录)集合或序列重新排列成按记录的某个数据项值递增或者递减的序列。
2>在为排序依据的数据项称为“排序项”,也成为排序的关键码,关键码分为主关键码和次关键码。
3>排序分为内部排序和外部排序。内部排序指的是在排序的整个过程中,记录全部存放在计算机的内存中,并且在内存中调整记录之间的相对位置,在此期间没有进行内、外存的数据交换。 外部排序指的是在排序过程中,记录的主要部分存放在外存中,借助于内存逐步调整记录之间的相对位置。在这个过程中,需要不断地在内、外存之间交换数据。
4>排序问题的记录采用线性结构。顺序表具有随机存取的特性,存取任意一个数据元素的时间复杂度为O(1),而链表不具有随机存取的特性,存取任意一个数据元素的时间复杂度为O(n),所以排序算法是基于顺序表设计的。
直接插入排序
直接插入排序(direct Insert Sort)的基本思想是:顺序地将待排序的记录按其关键码的大小插入到已排序的记录子序列的适当位置。

public void InsertSort(List<int> list)        {            for (int i = 0; i < list.Count; i++)            {                if (list[i]<list[i-1])                {                    int temp = list[i];                    int j = 0;                    for ( j = i-1; j >=0&&temp<list[j]; j--)                    {                        list[j + 1] = list[j];                    }                    list[j + 1] = temp;                }            }        }

直接插入排序算法的时间复杂度分为最好、最坏和随机三种情况:
(1) 最好的情况是顺序表中的记录已全部排好序。这时外层循环的次数为n-1,内层循环的次数为 0。这样,外层循环中每次记录的比较次数为 1,所以直接插入排序算法在最好情况下的时间复杂度为 O(n)。
(2) 最坏情况是顺序表中记录是反序的。这时内层循环的循环系数每次均为 i。因此,直接插入排序算法在最坏情况下的时间复杂度为O(n2)。
(3) 如果顺序表中的记录的排列是随机的,则记录的期望比较次数为n2/4。因此,直接插入排序算法在一般情况下的时间复杂度为O(n2)。
可以证明,顺序表中的记录越接近于有序,直接插入排序算法的时间效率越高,其时间效率在O(n)到O(n2)之间。
直接插入排序算法的空间复杂度为 O(1)。因此,直接插入排序算法是一种稳定的排序算法。
冒泡排序
冒泡排序(Bubble Sort)的基本思想是:将相邻的记录的关键码进行比较,若前面记录的关键码大于后面记录的关键码,则将它们交换,否则不交换。

 public void BunbleSorT(List<int> list)        {            int temp;            for (int i = 0; i < list.Count; i++)            {                for (int j = 0; j < list.Count-1; j++)                {                    if (list[j+1]<list[j])                    {                        temp = list[j + 1];                        list[j + 1] = list[j];                        list[j] = temp;                    }                }            }        }

冒泡排序算法的最好情况是记录已全部排好序,这时,循环 n-1 次,每次循环都因没有数据交换而退出。因此,冒泡排序算法在最好情况下的时间复杂度为O(n)。
冒泡排序算法的最坏情况是记录全部逆序存放,总的移动次数为比较次数的 3 倍,因为被进行一次比较,需要进行 3 次移动。因此,冒泡排序算法在最坏情况下的时间复杂度为O(n2)。
简单选择排序
简单选择排序(Simple Select Sort)算法的基本思想是:从待排序的记录序列中选择关键码最小(或最大)的记录并将它与序列中的第一个记录交换位置;然后从不包括第一个位置上的记录序列中选择关键码最小(或最大)的记录并将它与序列中的第二个记录交换位置;如此重复,直到序列中只剩下一个记录为止。

 public void SimpleSort(List<int> list)        {            int temp = 0;            int t = 0;            for (int i = 0; i < list.Count; i++)            {                t = i;                for (int j = i+1; j < list.Count; j++)                {                    if (list[t]>list[j])                    {                        t = j;                    }                }                temp = list[t];                list[t] = list[i];                list[i] = temp;            }        }

在简单选择排序中,第一次排序要进行 n-1 次比较,第二次排序要进行 n-2次比较,第 n-1 排序要进行 1 次比较,在各次排序时,记录的移动次数最好 0 次,最坏为 3 次,所以,总的移动次数最好为 0 次,最坏为 3 次。因此,简单选择排序算法的时间复杂度为O(n2)。
快速排序
快速排序(Quick Sort)的基本思想是:通过不断比较关键码,以某个记录为界(该记录称为支点),将待排序列分成两部分。其中,一部分满足所有记录的关键码都大于或等于支点记录的关键码,另一部分记录的关键码都小于支点记录的关键码。把以支点记录为界将待排序列按关键码分成两部分的过程,称为一次划分。对各部分不断划分,直到整个序列按关键码有序为止。

 public void QuickSort(List<int> list,int low,int high )        {            int i = low;            int j = high;            int temp = list[low];            while (i<j)            {                while (i<j)                {                    if (list[j]<temp)//小于基准的数字,把他存储在前面                    {                        list[i] = list[j];                        break;                    }                    j--;                }                while (i<j)                {                    if (list[i]>temp)                    {                        if (list[i]>temp)//大于基准的数字,把他存储在后面                        {                            list[j] = list[i];                            break;                        }                    }                    i++;                }            }            list[i] =temp;            QuickSort(list, low, i - 1);            QuickSort(list, i + 1, high);        }

快速排序算法的时间复杂度和每次划分的记录关系很大。如果每次选取的记录都能均分成两个相等的子序列,这样的快速排序过程是一棵完全二叉树结构(即个结点都把当前待排序列分成两个大小相当的子序列结点,n个记录待排序列的根结点的分解次数就构成了一棵完全二叉树),这时分解次数等于完全二叉树的深度log2n。每次快速排序过程无论把待排序列这样划分,全部的比较次数都接近于n-1 次,所以,最好情况下快速排序的时间复杂度为O(nlog2n)。快速排序算法的最坏情况是记录已全部有序,此时n个记录待排序列的根结点的分解次数就构成了一棵单右支二叉树。所以在最坏情况下快速排序算法的时间复杂度为O(n2)。一般情况下,记录的分布是随机的,序列的分解次数构成一棵二叉树,这样二叉树的深度接近于log2n,所以快速排序算法在一般情况下的时间复杂度为O(nlog2n)。 另外,快速排序算法是一种不稳定的排序的方法。

原创粉丝点击