演算法(第四版)C#題解——2.1

来源:https://www.cnblogs.com/ikesnowy/archive/2018/01/02/8178698.html
-Advertisement-
Play Games

寫在前面 整個項目都托管在了 Github 上:https://github.com/ikesnowy/Algorithms-4th-Edition-in-Csharp 這一節內容可能會用到的庫文件有 Sort和 SortData,同樣在 Github 上可以找到。 善用 Ctrl + F 查找題目 ...


寫在前面

整個項目都托管在了 Github 上:https://github.com/ikesnowy/Algorithms-4th-Edition-in-Csharp

這一節內容可能會用到的庫文件有 Sort和 SortData,同樣在 Github 上可以找到。

善用 Ctrl + F 查找題目。

習題&題解

2.1.1

題目

按照演算法 2.1 所示軌跡的格式給出選擇排序是如何將數組 E A S Y Q U E S T I O N 排序的。

解答

2.1.1

 

2.1.2

題目

在選擇排序中,一個元素最多可能會被交換多少次?平均可能會被交換多少次?

解答

最多會被交換 n 次,只要將一個有序數列迴圈右移一位就可以構造這樣的情況。

例如:

2.1.2

平均每個元素被交換了 N/N=1 次。(總共 N 個元素,總共發生了 N 次交換)

 

2.1.3

題目

構造一個含有 N 個元素的數組,使選擇排序(演算法 2.1)運行過程中 a[j] < a[min] (由此 min 會不斷更新)成功的次數最大。

解答

你需要一個逆序的數組。

例如:9 8 7 6 5 4 3 2 1

i=0 條件滿足 8 次,1 和 9 交換,1 8 7 6 5 4 3 2 9。

i=1 條件滿足 6 次,2 和 8 交換,1 2 7 6 5 4 3 8 9。

i=2 條件滿足 4 次,3 和 7 交換,1 2 3 6 5 4 7 8 9。

i=3 條件滿足 2 次,4 和 6 交換。1 2 3 4 5 6 7 8 9。

一共滿足了 8+6+4+2=20 次

 

2.1.4

題目

按照演算法 2.2 所示軌跡的格式給出插入排序是如何將數組 E A S Y Q U E S T I O N 排序的。

解答

2.1.4

 

2.1.5

題目

構造一個含有 N 個元素的數組,使插入排序(演算法 2.2)運行過程中內迴圈(for)的兩個判斷結果總是假。

解答

條件是:

j > 0 && less(a[j], a[j - 1])

第一個條件屬於迴圈計數用的條件,與數組元素無關;

第二個條件當 a[j] 和 a[j - 1] 是一組逆序對時滿足,因此這個條件總是為假 = 數組沒有逆序對 = 數組有序。

因此只要輸入已經排好序的數組即可。

逆序對:指序列中順序相反的兩個數,例如 1 2 3 4 5 7 6 8 9 中的 7 6。

 

2.1.6

題目

在所有主鍵都相同時,選擇排序和插入排序誰更快?

解答

插入排序更快。

選擇排序無論如何都需要 n + (n-1) + (n-2) + …  + 1 = n^2/2 次比較。

插入排序在這種情況下只需要 n 次比較。(所有主鍵相同 = 數組已排序)

 

2.1.7

題目

對於逆序數組,選擇排序和插入排序誰更快?

解答

假設比較的開銷小於等於交換的開銷,此時選擇排序更快,具體比較見下表。

  比較次數 交換次數
插入排序 ~N^2/2 ~N^2/2
選擇排序 ~N^2/2 N
 

2.1.8

題目

假設元素只可能有三種值,使用插入排序處理這樣一個隨機數組的運行時間是線性的還是平方級別的?或是介於兩者之間?

解答

平方級別。

如果數組中元素各不相同,那麼這個結論很容易證明(一般的插入排序)。

接下來我們證明有重覆元素的情況下,這個結論仍然成立:

首先對於插入排序過程中的某一時刻,我們有下圖這樣的一般情況:

image

其中,1,2,3 分別代表三種不同的取值以及其先後順序。

假設這是第 i 次插入前,如果第 i 次插入的是 1,我們需要交換 b+c 次,插入 2 則需要交換 c 次,插入 3 則不需要交換。

根據題意,這是一個隨機數組,我們假設其為均勻分佈,那麼三種取值的出現幾率相等。

第 i 次插入所需要的平均交換次數即為:

2.1.8

第 i 次插入後,b + 2c 視插入的元素不同會出現不同的變化:

如果插入的是 1,那麼 b+2c 的值不會變化。

如果插入的是 2,那麼 b+2c 的值增加 1。

如果插入的是 3,那麼 b+2c 的值增加 2。

同樣由於三種取值的概率相等,我們得出第 i + 1 次插入平均需要交換的次數為:

2.1.8.2

也就是說,平均每次插入都會使下一次插入的交換次數增加 1/3。

令 i=0,此時交換次數為 0,i+1 的交換次數即為 1/3,i+2 的交換次數即為 2/3,以此類推。

我們可以得出總交換次數:

2.1.8.3

由此證明,在元素取值為 3 種且出現概率相等時,插入排序的交換開銷時平方級別的。

比較開銷和交換開銷類似,一般情況下比較次數=交換次數+1,除非插入的數是已知最小的數(移動到最左側),這個時候比較次數和交換次數相等。

因此比較次數=交換次數+N-e,e 是一個不大於 N 的數,代表插入的數是已知最小的數這種情況發生的次數。

根據上式可以得出結論:在元素取值為 3 種且出現概率相等時,插入排序的比較開銷也是平方級別的。

綜合兩個結論即可證明插入排序的開銷在題目描述的情況下是平方級別的。

證明完畢。

 

2.1.9

題目

按照演算法 2.3 所示軌跡的格式給出希爾排序是如何將數組 E A S Y S H E L L S O R T Q U E S T I O N 排序的。

解答

2.1.9

 

2.1.10

題目

在希爾排序中為什麼在實現 h 有序時不使用選擇排序?

解答

對於部分有序的數組,插入排序比選擇排序快。

這個結論可以在中文版 P158, 英文版 P252 找到。

 

2.1.11

題目

將希爾排序中實時計算遞增序列改為預先計算並存儲在一個數組中。

解答

希爾排序的官方實現:https://algs4.cs.princeton.edu/21elementary/Shell.java.html

只要稍作修改即可,詳情見代碼。

代碼
/// <summary>
        /// 利用希爾排序將數組按升序排序。
        /// </summary>
        /// <param name="a">需要排序的數組。</param>
        public override void Sort<T>(T[] a)
        {
            int n = a.Length;
            int[] h = new int[2];   // 預先準備好的 h 值數組

            int hTemp = 1;
            int sequenceSize = 0;
            for (sequenceSize = 0; hTemp < n; sequenceSize++)
            {
                if (sequenceSize >= h.Length)  // 如果數組不夠大則雙倍擴容
                {
                    int[] expand = new int[h.Length * 2];
                    for (int j = 0; j < h.Length; j++)
                    {
                        expand[j] = h[j];
                    }
                    h = expand;
                }
                h[sequenceSize] = hTemp;
                hTemp = hTemp * 3 + 1;
            }

            for (int t = sequenceSize - 1; t >= 0; t--)
            {
                for (int i = h[t]; i < n; i++)
                {
                    for (int j = i; j >= h[t] && Less(a[j], a[j - h[t]]); j -= h[t])
                    {
                        Exch(a, j, j - h[t]);
                    }
                }
                Debug.Assert(IsHSorted(a, h[t]));
            }
            Debug.Assert(IsSorted(a));
        }

 

2.1.12

題目

令希爾排序列印出遞增序列的每個元素所帶來的比較次數和數組大小的比值。
編寫一個測試用例對隨機 Double 數組進行希爾排序,驗證該值是一個小常數,數組大小按照 10 的冪次遞增,不小於 100。

解答

結果截圖如下,同一個 h 值對應的比值在數組大小不同時保持為一個小常數:

image

代碼
class Program
{
    // 查看最後結果
    // 可以發現相同的 h 在數組大小不同時所產生的比值十分接近。
    static void Main(string[] args)
    {
        Random random = new Random();
        ShellSort sort = new ShellSort();

        int size = 100;
        for (int i = 0; i < 5; i++)
        {
            double[] a = new double[size];
            for (int j = 0; j < size; j++)
            {
                a[j] = random.NextDouble() * 100;
            }
            Console.WriteLine("ArraySize:" + size);
            sort.Sort(a);
            size *= 10;
        }
    }
}

 

2.1.13

題目

紙牌排序。

說說你會如何將一副撲克牌按花色排序(花色排序是黑桃、紅桃、梅花和方片),
限制條件是所有牌都是背面朝上排成一列,而你一次只能翻看兩張牌或者交換兩張牌(保持背面朝上)。

解答

可以用冒泡排序做,具體方法如下:

翻一二兩張,是逆序對就交換,否則什麼也不做
翻二三兩張,是逆序對就交換,否則什麼也不做
一直到最後,可以保證最右側的是最大花色的牌
然後不斷重覆上述過程,就可以完全排序

 

2.1.14

題目

出列順序。

說說你會如何將一副撲克牌排序,
限制條件是只能查看最上面的兩張牌,交換最上面的兩張牌,或是將最上面的一張牌放到這摞牌的最下麵。

解答

用一種類似於冒泡的方法做,具體步驟為:

重覆以下步驟,直到全部完成一遍之後沒有發生交換
    重覆以下步驟 n-1 次
        如果頂端兩張牌逆序,那麼交換它們。
        將第一張牌放到牌堆底部。

具體步驟圖:

InkedWP_20171126_21_29_53_Pro_LI2

我們將牌排成一個環,用一支筆隔開,這裡我們標記筆的左側是牌堆頂部,右側是牌堆底部。

那麼我們能做的三個操作在這裡即為:

查看最上面兩張牌 = 從筆的位置開始,逆時針查看兩張牌。

交換最上面兩張牌 = 從筆的位置開始,逆時針選擇兩張牌並交換。

將最上面的一張牌放到最下麵 = 將筆的位置逆時針移動一位。

 

下麵我們開始執行開始說過的操作,目標順序是自頂向下從小到大排列。

初始情況如圖所示:

WP_20171126_21_23_47_Pro_LI

梅花7 和 紅桃4 不是逆序對,直接將筆逆時針移動一位。

WP_20171126_21_24_07_Pro_LI

紅桃4 和 黑桃6 不是逆序對,我們將筆逆時針移動一位。

WP_20171126_21_24_42_Pro_LI

再看 黑桃6 和 方片A,是逆序對,我們交換並將筆逆時針移動一位。

WP_20171126_21_24_56_Pro_LI

再看 黑桃6 和 紅桃J,是逆序對,我們交換並將筆逆時針移動一位。

WP_20171126_21_25_09_Pro_LI

現在我們已經操作了 4 次,內部迴圈結束,我們將筆放回初始位置。

WP_20171126_21_25_19_Pro_LI

這樣一次迴圈之後,我們就把最大的牌放在了最下麵,依次類推即可完全排序。

 

2.1.15

題目

昂貴的交換。

一家貨運公司的一位職工得到了一項任務,需要將若幹大貨箱按照發貨時間擺放。
比較發貨時間很容易(對照標簽即可),但將兩個貨箱交換位置則很困難(移動麻煩)。
倉庫已經快滿了,只有一個空閑的倉位。這位職員應該使用哪種排序演算法呢?

解答

選擇排序

交換(也就是 Exch() 方法)需要一個額外空間,這裡的條件滿足。

現在我們應該使交換次數最少,選擇排序只需要 N 次交換,比插入排序平均 N^2/4 少(N > 2)。

 

2.1.16

題目

驗證。

編寫一個 check() 方法,調用 sort() 對任意數組排序。
如果排序成功而且數組中的所有對象均沒有被修改則返回 true,否則返回 false。
不要假設 sort() 只能通過 exch() 來移動數據,可以信任並使用 Array.sort()。

解答

如果移動數據時新建了對象,那麼雖然值沒有改變,但是數組中的對象被修改了。

代碼

插入排序中的 Exch() 換成瞭如下方式:

string temp = new string(s[i].ToCharArray());
s[i] = s[min];
s[min] = temp;

全部程式代碼如下:

using System;

namespace _2._1._16
{
    /*
     * 2.1.16
     * 
     * 驗證。
     * 編寫一個 check() 方法,
     * 調用 sort() 對任意數組排序。
     * 如果排序成功而且數組中的所有對象均沒有被修改則返回 true,
     * 否則返回 false。
     * 不要假設 sort() 只能通過 exch() 來移動數據,
     * 可以信任並使用 Array.sort()。
     * 
     */
    public class Program
    {
        static void Main(string[] args)
        {
            string[] test = new string[5] { "a", "b", "d", "c", "e" };
            Console.WriteLine(CheckArraySort(test));
            Console.WriteLine(CheckSelectionSort(test));
        }

        /// <summary>
        /// 測試 Array.Sort() 方法。
        /// </summary>
        /// <param name="a">用於測試的數組。</param>
        /// <returns>如果數組對象沒有改變,返回 true,否則返回 false。</returns>
        static bool CheckArraySort(string[] a)
        {
            string[] backup = new string[a.Length];
            a.CopyTo(backup, 0);

            Array.Sort(a);

            foreach (string n in a)
            {
                bool isFind = false;
                for (int i = 0; i < a.Length; i++)
                {
                    if (ReferenceEquals(n, backup[i]))
                    {
                        isFind = true;
                        break;
                    }
                }
                if (!isFind)
                {
                    return false;
                }
            }

            return true;
        }

        /// <summary>
        /// 測試選擇排序。
        /// </summary>
        /// <param name="a">用於測試的數組。</param>
        /// <returns>如果數組對象沒有改變,返回 true,否則返回 false。</returns>
        static bool CheckSelectionSort(string[] a)
        {
            string[] backup = new string[a.Length];
            a.CopyTo(backup, 0);

            SelectionSort(a);

            foreach (string n in a)
            {
                bool isFind = false;
                for (int i = 0; i < a.Length; i++)
                {
                    if (ReferenceEquals(n, backup[i]))
                    {
                        isFind = true;
                        break;
                    }
                }
                if (!isFind)
                {
                    return false;
                }
            }

            return true;
        }

        /// <summary>
        /// 選擇排序,其中的交換部分使用新建對象並複製的方法。
        /// </summary>
        /// <param name="s">用於排序的數組。</param>
        public static void SelectionSort(string[] s)
        {
            for (int i = 0; i < s.Length; i++)
            {
                int min = i;
                for (int j = i + 1; j < s.Length; j++)
                {
                    if (s[j].CompareTo(s[min]) < 0)
                    {
                        min = j;
                    }
                }
                string temp = new string(s[i].ToCharArray());
                s[i] = s[min];
                s[min] = temp;
            }
        }
    }
}

 

2.1.17

題目

動畫。

修改插入排序和選擇排序的代碼,使之將數組內容繪製成正文中所示的棒狀圖。
在每一輪排序後重繪圖片來產生動畫效果,並以一張“有序”的圖片作為結束,即所有的圓棒均已按照高度有序排列。
提示:使用類似於正文中的用例來隨機生成 Double 值,在排序代碼的適當位置調用 show() 方法,併在 show() 方法中清理畫布並繪製棒狀圖。

解答

選擇排序:

選擇排序

插入排序:

插入排序

代碼

使用一個 timer 按一定時間重繪數組,排序演算法裡面一次迴圈後等待一段時間再進行下一次迴圈。

這裡排序演算法是另開線程運行的,防止 Sleep 的時候讓程式無響應。

選擇排序:

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;

namespace _2._1._17
{
    public partial class Form2 : Form
    {
        double[] randomDoubles;
        public Form2(int N)
        {
            InitializeComponent();
            this.randomDoubles = new double[N];
            Random random = new Random();
            for (int i = 0; i < N; i++)
            {
                this.randomDoubles[i] = random.NextDouble() * 0.8 + 0.2;
            }
            drawPanel();

            this.timer1.Interval = 60;
            this.timer1.Start();

            Thread thread = new Thread(new ThreadStart(this.SelectionSort));
            thread.IsBackground = true;
            thread.Start();
        }

        /// <summary>
        /// 選擇排序。
        /// </summary>
        private void SelectionSort()
        {
            for (int i = 0; i < this.randomDoubles.Length; i++)
            {
                int min = i;
                for (int j = i; j < this.randomDoubles.Length; j++)
                {
                    if (this.randomDoubles[min] > this.randomDoubles[j])
                    {
                        min = j;
                    }
                }
                double temp = this.randomDoubles[i];
                this.randomDoubles[i] = this.randomDoubles[min];
                this.randomDoubles[min] = temp;
                Thread.Sleep(1000);
            }
        }

        /// <summary>
        /// 在屏幕上用柱形圖繪製數組。
        /// </summary>
        private void drawPanel()
        {
            Graphics graphics = this.CreateGraphics();
            graphics.Clear(this.BackColor);
            graphics.TranslateTransform(0, this.Height);
            graphics.ScaleTransform(1, -1);
            Rectangle clientRect = this.ClientRectangle;
            Rectangle drawRect = new Rectangle(clientRect.X + 10, clientRect.Y + 10, clientRect.Width - 10, clientRect.Height - 10);

            PointF[] barX = new PointF[this.randomDoubles.Length];
            float unitX = (float)drawRect.Width / this.randomDoubles.Length;
            unitX -= 4;

            barX[0] = new PointF(4, drawRect.Top);
            for (int i = 1; i < this.randomDoubles.Length; i++)
            {
                barX[i] = new PointF(2 + unitX + barX[i - 1].X, drawRect.Top);
            }

            RectangleF[] bars = new RectangleF[this.randomDoubles.Length];
            for (int i = 0; i < this.randomDoubles.Length; i++)
            {
                SizeF size = new SizeF(unitX, (float)this.randomDoubles[i] * drawRect.Height);
                bars[i] = new RectangleF(barX[i], size);
            }

            graphics.FillRectangles(Brushes.Black, bars);
            graphics.Dispose();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            drawPanel();
        }
    }
}

插入排序:

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;

namespace _2._1._17
{
    public partial class Form3 : Form
    {
        double[] randomDoubles;
        public Form3(int N)
        {
            InitializeComponent();
            this.randomDoubles = new double[N];
            Random random = new Random();
            for (int i = 0; i < N; i++)
            {
                this.randomDoubles[i] = random.NextDouble() * 0.8 + 0.2;
            }
            drawPanel();

            this.timer1.Interval = 60;
            this.timer1.Start();

            Thread thread = new Thread(new ThreadStart(this.InsertionSort));
            thread.IsBackground = true;
            thread.Start();
        }

        /// <summary>
        /// 插入排序。
        /// </summary>
        private void InsertionSort()
        {
            for (int i = 0; i < this.randomDoubles.Length; i++)
            {
                for (int j = i; j > 0 && this.randomDoubles[j] < this.randomDoubles[j - 1]; j--)
                {
                    double temp = this.randomDoubles[j];
                    this.randomDoubles[j] = this.randomDoubles[j - 1];
                    this.randomDoubles[j - 1] = temp;
                    Thread.Sleep(500);
                }
            }
        }

        /// <summary>
        /// 在屏幕上用柱形圖繪製數組。
        /// </summary>
        private void drawPanel()
        {
            Graphics graphics = this.CreateGraphics();
            graphics.Clear(this.BackColor);
            graphics.TranslateTransform(0, this.Height);
            graphics.ScaleTransform(1, -1);
            Rectangle clientRect = this.ClientRectangle;
            Rectangle drawRect = new Rectangle(clientRect.X + 10, clientRect.Y + 10, clientRect.Width - 10, clientRect.Height - 10);

            PointF[] barX = new PointF[this.randomDoubles.Length];
            float unitX = (float)drawRect.Width / this.randomDoubles.Length;
            unitX -= 4;

            barX[0] = new PointF(4, drawRect.Top);
            for (int i = 1; i < this.randomDoubles.Length; i++)
            {
                barX[i] = new PointF(2 + unitX + barX[i - 1].X, drawRect.Top);
            }

            RectangleF[] bars = new RectangleF[this.randomDoubles.Length];
            for (int i = 0; i < this.randomDoubles.Length; i++)
            {
                SizeF size = new SizeF(unitX, (float)this.randomDoubles[i] * drawRect.Height);
                bars[i] = new RectangleF(barX[i], size);
            }

            graphics.FillRectangles(Brushes.Black, bars);
            graphics.Dispose();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            drawPanel();
        }
    }
}

 

2.1.18

題目

可視軌跡。
修改你為上一題給出的解答,為插入排序和選擇排序生成和正文中類似的可視軌跡。
提示:使用 setYscale() 函數是一個明智的選擇。
附加題:添加必要的代碼,與正文中的圖片一樣用紅色和灰色強調不同角色的元素。

解答

選擇排序

選擇排序

插入排序

插入排序

代碼

與上題類似,但要特別標出移動的元素。

選擇排序:

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;

namespace _2._1._18
{
    public partial class Form2 : Form
    {
        double[] randomDoubles;
        int sortI;
        int sortJ;
        int sortMin;
        public Form2(int N)
        {
            InitializeComponent();
            this.randomDoubles = new double[N];
            Random random = new Random();
            for (int i = 0; i < N; i++)
            {
                this.randomDoubles[i] = random.NextDouble() * 0.8 + 0.2;
            }
        }

        /// <summary>
        /// 選擇排序。
        /// </summary>
        private void SelectionSort()
        {
            for (this.sortI = 0; this.sortI < this.randomDoubles.Length; this.sortI++)
            {
                this.sortMin = this.sortI;
                for (this.sortJ = this.sortI; this.sortJ < this.randomDoubles.Length; this.sortJ++)
                {
                    if (this.randomDoubles[this.sortMin] > this.randomDoubles[this.sortJ])
                    {
                        this.sortMin = this.sortJ;
                    }
                }
                drawPanel();
                double temp = this.randomDoubles[this.sortI];
                this.randomDoubles[this.sortI] = this.randomDoubles[this.sortMin];
                this.randomDoubles[this.sortMin] = temp;
                Thread.Sleep(1000);
            }
        }

        /// <summary>
        /// 繪製柱形圖。
        /// </summary>
        private void drawPanel()
        {
            Graphics graphics = this.CreateGraphics();
            graphics.Clear(this.BackColor);
            graphics.TranslateTransform(0, this.Height);
            graphics.ScaleTransform(1, -1);
            Rectangle clientRect = this.ClientRectangle;
            Rectangle drawRect = new Rectangle(clientRect.X + 10, clientRect.Y + 10, clientRect.Width - 10, clientRect.Height - 10);

            PointF[] barX = new PointF[this.randomDoubles.Length];
            float unitX = (float)drawRect.Width / this.randomDoubles.Length;
            unitX -= 4;

            barX[0] = new PointF(4, drawRect.Top);
            for (int i = 1; i < this.randomDoubles.Length; i++)
            {
                barX[i] = new PointF(2 + unitX + barX[i - 1].X, drawRect.Top);
            }

            RectangleF[] bars = new RectangleF[this.randomDoubles.Length];
            for (int i = 0; i < this.randomDoubles.Length; i++)
            {
                SizeF size = new SizeF(unitX, (float)this.randomDoubles[i] * drawRect.Height);
                bars[i] = new RectangleF(barX[i], size);
            }

            for (int i = 0; i < bars.Length; i++)
            {
                if (i == this.sortMin)
                {
                    graphics.FillRectangle(Brushes.Red, bars[i]);
                }
                else if (i < this.sortI)
                {
                    graphics.FillRectangle(Brushes.Gray, bars[i]);
                }
                else
                {
                    graphics.FillRectangle(Brushes.Black, bars[i]);
                }
            }
            graphics.Dispose();
        }

        private void Form2_Shown(object sender, EventArgs e)
        {
            SelectionSort();
        }
    }
}

插入排序

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;

namespace _2._1._18
{
    public partial class Form3 : Form
    {
        double[] randomDoubles;
        int sortI;
        int sortJ;
        int n = 0;
        public Form3(int N)
        {
            InitializeComponent();
            this.randomDoubles = new double[N];
            Random random = new Random();
            for (int i = 0; i < N; i++)
            {
                this.randomDoubles[i] = random.NextDouble() * 0.8 + 0.2;
            }
        }

        /// <summary>
        /// 插入排序。
        /// </summary>
        private void InsertionSort()
        {
            for (this.sortI = 0; this.sortI < this.randomDoubles.Length; this.sortI++)
            {
                for (this.sortJ = this.sortI; this.sortJ > 0 && this.randomDoubles[this.sortJ] < this.randomDoubles[this.sortJ - 1]; this.sortJ--)
                {
                    double temp = this.randomDoubles[this.sortJ];
                    this.randomDoubles[this.sortJ] = this
              
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 網路上流傳的大部分95%以上的程式都是跑不通的,應大部分同學要求,現寫了一個酒店管理信息系統。 是ssh的架構, 基於java的 。 貼2個截圖 第二個 ...
  • 題目描述 棟棟最近迷上了隨機演算法,而隨機數是生成隨機演算法的基礎。棟棟準備使用線性同餘法(Linear Congruential Method)來生成一個隨機數列,這種方法需要設置四個非負整數參數m,a,c,X[0],按照下麵的公式生成出一系列隨機數{Xn}: 其中mod m表示前面的數除以m的餘數。 ...
  • 作為複習總結的筆記,我羅列了幾個jdbc步驟,後邊舉個簡單的例子,其中的try塊請讀者自行處理. /* * 1.下載驅動包:com.mysql.jdbc.Driver;網上很多下載資源,自己找度娘,此處不再提供; * * 2.將驅動包導入項目,並add to build path,具體步驟去問度娘. ...
  • 一 概述 在我們講解NuGet前,我們先來看看一個例子。 1.例子: 假設現在開發一套系統,其中前端框架我們選擇Bootstrap,由於選擇Bootstrap作為前端框架,因此,在項目中,我們需要引入Bootstrap相關文件,大致會執行如下操作。 步驟一:下載Bootstrap文件 輸入Boots ...
  • 示例代碼: 執行結果圖: ...
  • 最近因為業務需求開發了一個介面用於接收數據,但是總有一些數據報出ORA-01704:字元串文字太長錯誤。仔細排查後發現,竟然是NCLOB類型欄位提示這個錯誤。NCLOB存儲空間有4G,怎麼也想不明白為什麼會報這個錯誤。原來因為介面插入數據採用字元串拼接的方式。 而oracle中會把字元串轉為varc ...
  • 1.定義一個枚舉,樂器類型 #region 樂器定義 public enum MusicNo:uint { /// <summary> /// //大鋼琴 /// </summary> AcousticGrandPiano = 0, /// <summary> ///明亮的鋼琴 /// </summ ...
  • 一、新建項目 打開vs2017,新建一個項目,命名為orm1 二、新建資料庫 打開 SqlServer資料庫,新建資料庫 orm1,並新建表 student 。 三、新建 ADO.NET 實體數據模型 這裡點擊 新建連接,新建資料庫連接。其實伺服器名輸入 . 代表本地伺服器,身份驗證選擇預設的Win ...
一周排行
    -Advertisement-
    Play Games
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...