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

来源:http://www.cnblogs.com/ikesnowy/archive/2017/06/27/7086980.html
-Advertisement-
Play Games

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


寫在前面

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

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

善用 Ctrl + F 查找題目。

習題 & 題解
練習(1.2.1~1.2.14)
1.2.1
題目

編寫一個 Point2D 的用例,從命令行接受一個整數 N。
在單位正方形中生成 N 個隨機點,然後計算兩點之間的最近距離。

解答

這裡自己實現了一個 Point2D 類(包含在了 Geometry 庫中)。

JAVA 版本參考:http://algs4.cs.princeton.edu/12oop/Point2D.java.html

求最近兩點只需要反覆調用 Point2D 類中的 DistTo() 方法就可以了。

代碼

Point2D 類

/// <summary>
    /// Point2D 二維點類。
    /// </summary>
    public sealed class Point2D : IComparable<Point2D>
    {
        public readonly static Comparer<Point2D> X_Order = new XOrder();
        public readonly static Comparer<Point2D> Y_Order = new YOrder();
        public readonly static Comparer<Point2D> R_Order = new ROrder();

        public double X { get; }
        public double Y { get; }
        public int Radius { get; set; }

        public Point2D(double x, double y)
        {
            if (double.IsInfinity(x) || double.IsInfinity(y))
            {
                throw new ArgumentException("x, y must be finite");
            }

            if (double.IsNaN(x) || double.IsNaN(y))
            {
                throw new ArgumentNullException("Coordinate cannot be NaN");
            }

            this.X = x;
            this.Y = y;
            this.Radius = 2;
        }

        /// <summary>
        /// 返回極半徑。
        /// </summary>
        /// <returns></returns>
        public double R()
        {
            return Math.Sqrt(X * X + Y * Y);
        }

        /// <summary>
        /// 返回極角。
        /// </summary>
        /// <returns></returns>
        public double Theta()
        {
            return Math.Atan2(Y, X);
        }

        /// <summary>
        /// 返回兩個點之間的角度。
        /// </summary>
        /// <param name="that">要計算角度的另一個點。</param>
        /// <returns></returns>
        private double AngleTo(Point2D that)
        {
            double dx = that.X - this.X;
            double dy = that.Y - this.Y;
            return Math.Atan2(dy, dx);
        }

        /// <summary>
        /// 判斷 a,b,c 三個點的關係,如果 {順時針, 共線, 逆時針} 則返回 {-1, 0, 1}。
        /// </summary>
        /// <param name="a">第一個點。</param>
        /// <param name="b">第二個點。</param>
        /// <param name="c">第三個點。</param>
        /// <returns></returns>
        public static int CCW(Point2D a, Point2D b, Point2D c)
        {
            double area2 = (b.X - a.X) * (c.Y - a.Y) - (b.Y - a.Y) * (c.X - a.X);
            if (area2 < 0)
                return -1;
            if (area2 > 0)
                return 1;
            return 0;
        }

        /// <summary>
        /// 返回 abc 三個點構成的三角形的面積的平方。
        /// </summary>
        /// <param name="a">第一個點。</param>
        /// <param name="b">第二個點。</param>
        /// <param name="c">第三個點。</param>
        /// <returns></returns>
        public static double Area2(Point2D a, Point2D b, Point2D c)
        {
            return (b.X - a.X) * (c.Y - a.Y) - (b.Y - a.Y) * (c.X - a.X);
        }


        /// <summary>
        /// 返回當前點到另一個點之間的距離。
        /// </summary>
        /// <param name="that">另一個點。</param>
        /// <returns></returns>
        public double DistanceTo(Point2D that)
        {
            double dx = this.X - that.X;
            double dy = this.Y - that.Y;

            return Math.Sqrt(dx * dx + dy * dy);
        }

        /// <summary>
        /// 返回當前點到另一個點之間的距離的平方。
        /// </summary>
        /// <param name="that">另一個點。</param>
        /// <returns></returns>
        public double DistanceSquareTo(Point2D that)
        {
            double dx = this.X - that.X;
            double dy = this.Y - that.Y;

            return dx * dx + dy * dy;
        }

        /// <summary>
        /// 繪製二維點。
        /// </summary>
        /// <param name="g">原點在左下方,y軸向上,x軸向右的畫布。</param>
        public void Draw(Graphics g)
        {
            g.FillEllipse(Brushes.Black, (int)X, (int)Y, Radius, Radius);
        }

        /// <summary>
        /// 實現 IComparable 介面。
        /// </summary>
        /// <param name="other">需要比較的另一個對象。</param>
        /// <returns></returns>
        public int CompareTo(Point2D other)
        {
            if (this.Y < other.Y)
                return -1;
            if (this.Y > other.Y)
                return 1;
            if (this.X < other.X)
                return -1;
            if (this.X > other.X)
                return 1;

            return 0;
        }

        /// <summary>
        /// 按照 X 順序比較。
        /// </summary>
        private class XOrder : Comparer<Point2D>
        {
            public override int Compare(Point2D x, Point2D y)
            {
                if (x.X < y.X)
                {
                    return -1;
                }

                if (x.X > y.X)
                {
                    return 1;
                }

                return 0;
            }
        }

        /// <summary>
        /// 按照 Y 順序比較。
        /// </summary>
        private class YOrder : Comparer<Point2D>
        {
            public override int Compare(Point2D x, Point2D y)
            {
                if (x.Y < y.Y)
                {
                    return -1;
                }
                if (x.Y > y.Y)
                {
                    return 1;
                }

                return 0;
            }
        }

        /// <summary>
        /// 按照極徑順序比較。
        /// </summary>
        private class ROrder : Comparer<Point2D>
        {
            public override int Compare(Point2D x, Point2D y)
            {
                double delta = (x.X * x.X + x.Y * x.Y) - (y.X * y.X + y.Y * y.Y);
                if (delta < 0)
                {
                    return -1;
                }

                if (delta > 0)
                {
                    return 1;
                }

                return 0;
            }
        }

        /// <summary>
        /// 按照 atan2 值順序比較。
        /// </summary>
        private class Atan2Order : Comparer<Point2D>
        {
            private Point2D parent;
            public Atan2Order() { }
            public Atan2Order(Point2D parent)
            {
                this.parent = parent;
            }
            public override int Compare(Point2D x, Point2D y)
            {
                double angle1 = parent.AngleTo(x);
                double angle2 = parent.AngleTo(y);
                if (angle1 < angle2)
                {
                    return -1;
                }
                else if (angle1 > angle2)
                {
                    return 1;
                }
                else
                {
                    return 0;
                }
            }
        }

        /// <summary>
        /// 按照極角順序比較。
        /// </summary>
        private class PolorOrder : Comparer<Point2D>
        {
            private Point2D parent;
            public PolorOrder() { }
            public PolorOrder(Point2D parent)
            {
                this.parent = parent;
            }
            public override int Compare(Point2D q1, Point2D q2)
            {
                double dx1 = q1.X - parent.X;
                double dy1 = q1.Y - parent.Y;
                double dx2 = q2.X - parent.X;
                double dy2 = q2.Y - parent.Y;

                if (dy2 >= 0 && dy2 < 0)
                {
                    return -1;
                }
                else if (dy2 >= 0 && dy1 < 0)
                {
                    return 1;
                }
                else if (dy1 == 0 && dy2 == 0)
                {
                    if (dx1 >= 0 && dx2 < 0)
                    {
                        return -1;
                    }
                    else if (dx2 >= 0 && dx1 < 0)
                    {
                        return 1;
                    }
                    else
                    {
                        return 0;
                    }
                }
                else
                {
                    return -CCW(this.parent, q1, q2);
                }
            }
        }

        /// <summary>
        /// 按照距離順序比較。
        /// </summary>
        private class DistanceToOrder : Comparer<Point2D>
        {
            private Point2D parent;
            public DistanceToOrder() { }
            public DistanceToOrder(Point2D parent)
            {
                this.parent = parent;
            }
            public override int Compare(Point2D p, Point2D q)
            {
                double dist1 = parent.DistanceSquareTo(p);
                double dist2 = parent.DistanceSquareTo(q);

                if (dist1 < dist2)
                {
                    return -1;
                }
                else if (dist1 > dist2)
                {
                    return 1;
                }
                else
                {
                    return 0;
                }
            }
        }

        public Comparer<Point2D> Polor_Order()
        {
            return new PolorOrder(this);
        }

        public Comparer<Point2D> Atan2_Order()
        {
            return new Atan2Order(this);
        }

        public Comparer<Point2D> DistanceTo_Order()
        {
            return new DistanceToOrder(this);
        }

        public override bool Equals(object obj)
        {
            if (obj == this)
            {
                return true;
            }
            if (obj == null)
            {
                return false;
            }
            if (obj.GetType() != this.GetType())
            {
                return false;
            }
            Point2D that = (Point2D)obj;
            return this.X == that.X && this.Y == that.Y;
        }

        public override string ToString()
        {
            return "(" + X + ", " + Y + ")";
        }

        public override int GetHashCode()
        {
            int hashX = X.GetHashCode();
            int hashY = Y.GetHashCode();
            return 31 * hashX + hashY;
        }

Main() 方法:

namespace _1._2._1
{
    /*
     * 1.2.1
     * 
     * 編寫一個 Point2D 的用例,從命令行接受一個整數 N。
     * 在單位正方形中生成 N 個隨機點,然後計算兩點之間的最近距離。
     * 
     */
    class Program
    {
        static void Main(string[] args)
        {

            Console.WriteLine("Type the value of N:");
            int N = int.Parse(Console.ReadLine());
            List<Point2D> pointlist = new List<Point2D>();
            Random random = new Random();

            if (N <= 2)
            {
                Console.WriteLine("Make sure there are 2 points at least");
                return;
            }

            //random.NextDouble() 返回一個 0~1 之間的 double 值
            for (int i = 0; i < N; ++i)
            {
                double x = random.NextDouble();
                double y = random.NextDouble();
                pointlist.Add(new Point2D(x, y));
            }

            double min = pointlist[0].DistanceTo(pointlist[1]);
            for (int i = 0; i < N; ++i)
            {
                for (int j = i + 1; j < N; ++j)
                {
                    double temp = pointlist[i].DistanceTo(pointlist[j]);
                    Console.WriteLine($"Checking Distance({i}, {j}): {temp}");
                    if (temp < min)
                    {
                        min = temp;
                    }
                }
            }

            Console.WriteLine($"\nThe minimal distance is {min}");
        }
    }
}
1.2.2
題目

編寫一個 Interval1D 的用例,從命令行接受一個整數 N。
從標準輸入中讀取 N 個間隔(每個間隔由一對 double 值定義)並列印出所有相交的間隔對。

解答

同樣實現了一個 Interval1D 類(位於 Geometry 庫)。

JAVA 版本參考:http://algs4.cs.princeton.edu/12oop/Interval1D.java.html

直接調用其中的 Intersect() 方法即可

代碼

Interval1D 類:

namespace Geometry
{
    /// <summary>
    /// 一維閉區間。
    /// </summary>
    public class Interval1D
    {
        public static readonly Comparer<Interval1D> Min_Order = new MinEndpointComparer();
        public static readonly Comparer<Interval1D> Max_Order = new MaxEndpointComparer();
        public static readonly Comparer<Interval1D> Length_Order = new LengthComparer();

        public double Min { get; }
        public double Max { get; }

        /// <summary>
        /// 構造函數。
        /// </summary>
        /// <param name="lo">一維區域的下界。</param>
        /// <param name="hi">一維區域的上界。</param>
        public Interval1D(double lo, double hi)
        {
            if (double.IsInfinity(lo) || double.IsInfinity(hi))
            {
                throw new ArgumentException("Endpoints must be finite");
            }
            if (double.IsNaN(lo) || double.IsNaN(hi))
            {
                throw new ArgumentException("Endpoints cannot be NaN");
            }

            if (lo <= hi)
            {
                this.Min = lo;
                this.Max = hi;
            }
            else
            {
                throw new ArgumentException("Illegal interval");
            }
        }

        /// <summary>
        /// 一維區域的長度。
        /// </summary>
        /// <returns>返回長度。</returns>
        public double Length()
        {
            return this.Max - this.Min;
        }

        /// <summary>
        /// 判斷目標區間是否被本區間包含。
        /// </summary>
        /// <param name="that">需要判斷是否被包含的區間。</param>
        /// <returns></returns>
        public bool Contains(Interval1D that)
        {
            return this.Min < that.Min && this.Max > that.Max;
        }

        /// <summary>
        /// 目標值是否處在區域內。如果目標值在區域內則返回 True,否則返回 False。
        /// </summary>
        /// <param name="x">需要判斷的值。</param>
        /// <returns></returns>
        public bool Contains(double x)
        {
            return x >= this.Min && x <= this.Max;
        }

        /// <summary>
        /// 判斷兩個區域是否相交。
        /// </summary>
        /// <param name="that">需要判斷相交的另一個區域。</param>
        /// <returns>如果相交則返回 True,否則返回 False。</returns>
        public bool Intersect(Interval1D that)
        {
            if (this.Max < that.Min || that.Max < this.Min)
                return false;

            return true;
        }

        /// <summary>
        /// 繪製一維區間。
        /// </summary>
        /// <param name="g">原點在左下方,y軸向上,x軸向右的畫布。</param>
        /// <param name="y">繪製一維區間的 y軸 坐標。</param>
        public void Draw(Graphics g, int y)
        {
            Point A = new Point((int)Min, y);
            Point B = new Point((int)Max, y);
            g.DrawLine(Pens.Black, A, B);
        }

        /// <summary>
        /// 將區域轉換為 string,返回形如 "[lo, hi]" 的字元串。
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            string s = "[" + this.Min + ", " + this.Max + "]";
            return s;
        }

        /// <summary>
        /// 判斷兩個區間是否相等。
        /// </summary>
        /// <param name="obj">相比較的區間。</param>
        /// <returns></returns>
        public override bool Equals(object obj)
        {
            if (obj == this)
            {
                return true;
            }
            if (obj == null)
            {
                return false;
            }
            if (obj.GetType() != this.GetType())
            {
                return false;
            }
            Interval1D that = (Interval1D)obj;
            return this.Min == that.Min && this.Max == that.Max;
        }

        /// <summary>
        /// 返回區間的哈希代碼。
        /// </summary>
        /// <returns></returns>
        public override int GetHashCode()
        {
            int hash1 = Min.GetHashCode();
            int hash2 = Max.GetHashCode();
            return 31 * hash1 + hash2;
        }

        private class MinEndpointComparer : Comparer<Interval1D>
        {
            public override int Compare(Interval1D a, Interval1D b)
            {
                if (a.Min < b.Min)
                {
                    return -1;
                }
                else if (a.Min > b.Min)
                {
                    return 1;
                }
                else if (a.Max < b.Max)
                {
                    return -1;
                }
                else if (a.Max > b.Max)
                {
                    return 1;
                }
                else
                {
                    return 0;
                }
            }
        }

        private class MaxEndpointComparer : Comparer<Interval1D>
        {
            public override int Compare(Interval1D a, Interval1D b)
            {
                if (a.Max < b.Max)
                {
                    return -1;
                }
                else if (a.Max > b.Max)
                {
                    return 1;
                }
                else if (a.Min < b.Min)
                {
                    return -1;
                }
                else if (a.Min > b.Min)
                {
                    return 1;
                }
                else
                {
                    return 0;
                }
            }
        }

        private class LengthComparer : Comparer<Interval1D>
        {
            public override int Compare(Interval1D a, Interval1D b)
            {
                double alen = a.Length();
                double blen = b.Length();

                if (alen < blen)
                {
                    	   

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 很多電腦愛好者對於Win10內置的PIN碼功能不太瞭解,很多朋友都還沒有使用。其實,創建PIN碼可以提到密碼使用,當你登錄到Windows和其它應用服務時,可以通過PIN碼替代輸入賬戶密碼,提升安全性。話不多說,以下是Win10開啟PIN碼設置使用教程,步驟如下。 一、從Win10左下角的開始菜單, ...
  • 對於游戲玩家來說,對顯卡的關註度要高於電腦其它硬體,一般來說,顯卡越好,游戲性能往往越強。不過要持續發揮顯卡的最佳游戲性能,經常更新顯卡驅動也是很有必要的。那麼筆記本顯卡驅動怎麼更新?下麵小編以自己的Win10筆記本為例,教大家如何升級筆記本顯卡驅動。 Win10筆記本顯卡驅動更新升級方法 升級筆記 ...
  • 1.下載最新的openssh包 http://www.openssh.com/portable.html#http 2.升級openssh之前要先打開伺服器telnet,通過telnet登錄伺服器,因為升級過程中會導致ssh暫時不能用 打開linux telnet服務: 查看telnet是否已經安裝 ...
  • 環境:筆記本 + 家用WIFI + 公司WIFI + VMware + CentOS6.8 + Xshell 問題描述:初學Linux時,用筆記本裝了虛擬機(單網卡),想實現linux在家和公司都能夠無線連網,但又不想上網地點變動之後每次手動輸入IP登錄Xshell。 解決思路:增加一塊網卡(eth ...
  • 一、簡介 1、認識 加密網頁(https): tcp:443 明文網頁(http): tcp:80 survey.netcraft.net --這個網站上可以查到最新的網站伺服器的使用率 超文本傳輸協議(HTTP,HyperText Transfer Protocol)是互聯網上應用最為廣泛的一種網 ...
  • select系統調用的的用途是:在一段指定的時間內,監聽用戶感興趣的文件描述符上可讀、可寫和異常等事件。 select 機制的優勢 為什麼會出現select模型? 先看一下下麵的這句代碼: 這是用來接收數據的,在預設的阻塞模式下的套接字里,recv會阻塞在那裡,直到套接字連接上有數據可讀,把數據讀到 ...
  • 在ASP.NET MVC中來實現主題的切換一般有兩種方式,一種是通過切換皮膚的css和js引用,一種就是通過重寫視圖引擎。通過重寫視圖引擎的方式更加靈活,因為我不僅可以在不同主題下麵佈局和樣式不一樣,還可以讓不同的主題下麵顯示的數據條目不一致,就是說可以在某些主題下麵添加一下個性化的東西。 本篇我將 ...
  • 本文版權歸博客園和作者吳雙本人共同所有 轉載和爬蟲請註明原文地址 www.cnblogs.com/tdws 一.寫在前面 適配器模式(Adapter) 可用來在現有介面和不相容的類之間進行適配。有助於避免大規模改寫現有客戶代碼,其工作機制是對現有類的介面進行包裝,這樣客戶程式就能使用這個並非為其量身 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...