예제 #1
0
        static void Main(string[] args)
        {
            Console.WriteLine("N\t准确值\t估计值\t比值");
            QuickSortAnalyze sort = new QuickSortAnalyze();
            int N         = 100;
            int trialTime = 500;

            for (int i = 0; i < 3; i++)
            {
                int   sumOfCompare = 0;
                int[] a            = new int[N];
                for (int j = 0; j < trialTime; j++)
                {
                    for (int k = 0; k < N; k++)
                    {
                        a[k] = k;
                    }
                    SortCompare.Shuffle(a);
                    sort.Sort(a);
                    sumOfCompare += sort.CompareCount;
                }
                int    averageCompare   = sumOfCompare / trialTime;
                double estimatedCompare = 2 * N * Math.Log(N);
                Console.WriteLine(N + "\t" + averageCompare + "\t" + (int)estimatedCompare + "\t" + averageCompare / estimatedCompare);
                N *= 10;
            }
        }
예제 #2
0
        static void Main(string[] args)
        {
            // 每次只让枢轴变为已排序,这就是最坏情况。
            // 这种时候枢轴是当前子数组的最大值/最小值。
            // 由于在我们的实现中总是取子数组的第一个元素作为枢轴。
            // 因此一个已排序的数组可以达到最坏情况,比较次数达到 O(n^2)。
            // 如果换作取最后一个元素,最坏情况会变成逆序数组。
            // 我们的实现中如果碰到与枢轴相等的元素也会停止循环,
            // 因此如果数组中有重复的元素会减少比较次数。
            //
            // 答案:
            // 1 2 3 4 5 6 7 8 9 10
            // 2 3 4 5 6 7 8 9 10 11
            // 3 4 5 6 7 8 9 10 11 12
            // 4 5 6 7 8 9 10 11 12 13
            // 5 6 7 8 9 10 11 12 13 14
            // 6 7 8 9 10 11 12 13 14 15
            QuickSortAnalyze quick = new QuickSortAnalyze
            {
                NeedShuffle = false   // 关闭开始的打乱操作。
            };

            int[] a = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
            quick.Sort(a);
            Console.WriteLine(quick.CompareCount);
        }
        static void Main(string[] args)
        {
            // 根据书中的命题 U(中文版 P221,英文版 P347),
            // 当 k = 0 时,比较次数 ~2N。
            // 也可以参考快速排序的分析
            // Cn 代表找出 n 个元素的最小值所需的比较次数
            // Cn = 1/n * (n+1) + 1/n * (n+1+C1) +...+ 1/n * (n+1+C(n-1))
            // Cn = n+1 + 1/n * (C1 + ... + C(n-1))
            // nCn = n(n+1) + ... + C(n-1)
            // (n-1)C(n-1) = n(n-1) + C0 + ... + C(n-2)
            // nCn - (n-1)C(n-1) = 2n + C(n-1)
            // nCn = 2n + nC(n-1)
            // Cn = 2 + C(n-1)
            // Cn = 2n-2, n > 1.

            var multiBy10  = 5;
            var repeatTime = 100;
            var n          = 10000;

            Console.WriteLine("n\tAverage Compare");
            for (var i = 0; i < multiBy10; i++)
            {
                long totalCompare = 0;
                for (var j = 0; j < repeatTime; j++)
                {
                    var quick = new QuickSortAnalyze();
                    quick.Select(GetRandomArray(n), 0);
                    totalCompare += quick.CompareCount;
                }
                Console.WriteLine("10^" + (i + 4) + "\t" + totalCompare / repeatTime);
                n *= 10;
            }
        }
        static void Main(string[] args)
        {
            // 证明
            // 我们设 C0(n) 代表将 n 个不重复元素排序时大小为 0 的数组的数量。
            // 同理有 C1(n) 和 C2(n) 代表大小为 1 的数组的数量和大小为 2 的数组的数量。
            // 设 k 代表切分位置,显然切分位置随机且概率相等,在 1~n 之间均匀分布。
            // 根据条件,三者都满足下式。
            // C(n) = 1/n sum(C(k - 1) + C(n - k)), k=1,2,...,n
            // 显然 sum(C(k - 1)) = sum(C(n - k)), k=1,2,...,n
            // 于是可以化简为
            // C(n) = 2/n sum(C(k - 1)), k=1,2,...,n
            // nC(n) = 2 * sum(C(k-1)), k=1,2,...,n
            // 同理有
            // (n-1)C(n-1) = 2 * sum(C(k-1)), k = 1,2,...,n-1
            // 相减得到递推式
            // nC(n) - (n-1)C(n-1) = 2*C(n-1)
            // C(n) = (n+1)/n * C(n-1)
            // 利用累乘法可以求得通项公式
            // C(n)=C(k)*(n+1)/(k+1), n>k
            // 对于 C0 有 C0(0)=1, C0(1)=0
            // C0(2)=C(0)+C(1)=1
            // C0(n)=(n+1)/3, n>2
            // 对于 C1 有 C1(0)=0, C1(1)=1
            // C1(2)=C1(0)+C1(1)=1
            // C1(n)=(n+1)/3, n>2
            // 对于 C2 有 C2(0)=C2(1)=0, C2(2)=1
            // C2(3)=1/3*2*(C2(0)+C2(1)+C2(2))=2/3
            // C2(n)=C2(3)*(n+1)/4=(n+1)/6, n>3
            // 结论
            // C0(n)=C1(n)=(n+1)/3, C2(n)=(n+1)/6
            var n    = 1000;
            var sort = new QuickSortAnalyze();

            Console.WriteLine("n\t0\t1\t2");
            for (var i = 0; i < 5; i++)
            {
                var a = new int[n];
                for (var j = 0; j < n; j++)
                {
                    a[j] = j;
                }
                SortCompare.Shuffle(a);
                sort.Sort(a);
                Console.WriteLine(n + "\t" + sort.Array0Num + "\t" + sort.Array1Num + "\t" + sort.Array2Num);
                n *= 2;
            }
        }
        static void Main(string[] args)
        {
            // 约为 NlogN 次
            var sort = new QuickSortAnalyze();
            var N    = 100;

            Console.WriteLine("N\tCompare\tNlogN");
            for (var i = 0; i < 4; i++)
            {
                var a = new int[N];
                for (var j = 0; j < a.Length; j++)
                {
                    a[j] = 1;
                }
                sort.Sort(a);
                Console.WriteLine(N + "\t" + sort.CompareCount + "\t" + N * Math.Log(N) / Math.Log(2));
                N *= 10;
            }
        }
        static void Main(string[] args)
        {
            QuickSortAnalyze quick = new QuickSortAnalyze
            {
                NeedShuffle = false,            // 关闭打乱
                NeedPath    = true              // 显示排序轨迹
            };

            int[] a = QuickBest.Best(10);
            for (int i = 0; i < 10; i++)
            {
                Console.Write(a[i] + " ");
            }
            Console.WriteLine();
            quick.Sort(a);
            for (int i = 0; i < 10; i++)
            {
                Console.Write(a[i] + " ");
            }
            Console.WriteLine();
        }
        static void Main(string[] args)
        {
            // 插入排序
            Console.WriteLine("Insertion Sort");
            Test(new InsertionSort(), 7, 1);
            // 选择排序
            Console.WriteLine("Selection Sort");
            Test(new SelectionSort(), 7, 1);
            // 希尔排序
            Console.WriteLine("Shell Sort");
            Test(new ShellSort(), 7, 1);
            // 归并排序
            Console.WriteLine("Merge Sort");
            Test(new MergeSort(), 7, 1);
            // 快速排序
            Console.WriteLine("Quick Sort");
            var quick = new QuickSortAnalyze
            {
                NeedShuffle = false,
                NeedPath    = false
            };

            Test(quick, 7, 1);
            // 堆排序
            Console.WriteLine("Heap Sort");
            var array = new Item <int> [7];

            for (var i = 0; i < 7; i++)
            {
                array[i] = new Item <int>(i, 1);
            }
            Heap.Sort(array);
            for (var i = 0; i < 7; i++)
            {
                Console.Write(array[i].Index + " ");
            }
            Console.WriteLine();
        }