日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

算法-第四版

發布時間:2023/12/20 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 算法-第四版 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

算法是一種思維模式
思路+抽象解決問題的方案

總結
數據結構的基本存儲方式就是鏈式和順序兩種
基本操作就是增刪改查
遍歷方式無非迭代和遞歸

算法-第四版

一、基礎
本書的目的是研究多種重要而實用的算法,即適合用計算機實現的解決問題的方法。
和算法關系最緊密的是數據結構,即便于算法操作的組織數據的方法 。
本章介紹的就是學習算法和數據結構 所需要的基本工具。

基礎編程模型
數據抽象并定義抽象數據類型(ADT)以進行模塊化編程
三種基礎的抽象數據類型:背包、隊列和棧
用數組、變長數組和鏈表實現了背包、隊列和棧的 API//它們是全書算法實現的起點和樣板
性能是算法研究的一個核心問題。1.4 節描述了分析算法性能的方法
我們的基本做法是科學式的,即先對性能提出假設,建立數學模型,然后用多種實驗驗證它們,必要時重復這個過程
我們用一個連通性問題作為例子結束本章,它的解法所用到的算法和數據結構可以實現經典的 union-find (?)抽象數據結構

算法
編寫一段計算機程序一般都是實現一種已有的方法來解決某個問題。
這種方法大多 和使用的編程語言無關——它適用于各種計 算機以及編程語言。
是這種方法而非計算機程序本身描述了解決問題的步驟。
在計算機科學領域,我們用算法這個詞來描述一種有限、確定、有效的并適合用計算機程序來實現的解決問題的方法。算法是計算機科學的基礎,是這個領域研究的核心。

要定義一個算法,我們可以用自然語言 描述解決某個問題的過程或是編寫一段程序 來實現這個過程。

// 歐幾里得算法-自然語言描述 // 計算兩個非負整數 p 和 q 的最大公約數:若 q 是 0,則最大公約數為 p。 // 否則,將 p 除以 q得到余數r,p和q的最大公約數即為q和 r 的最大公約數。 // Java 語言描述public static int gcd(int p, int q) {if (q == 0) return p;int r = p % q;return gcd(q, r);}

在本書中,我們將用計算機程序來描述算法。這樣做的重要原因之一是可以更容易地驗證它們是否 如所要求的那樣有限、確定和有效

我們關注的大多數算法都需要適當地組織數據,而為了組織數據就產生了數據結構,數據結構也是計算機科學研究的核心對象,它和算法的關系非常密切
學習算法的主要原因是它們能節約非常多的資源,甚至能夠讓我們完成一些本不可能完成的任務

我們所研究的基礎算法在許多應用領域都是解決困難問題的有效方法
在本書中,我們的重點是用最簡潔的方式實現優秀的算法
為一項任務選擇最合適的算法是困難的,這可能會需要復雜的數學分析。
計算機科學中研究這種問題的分支叫做算法分析。通過分析,我們將要學習的許多算法都有著優秀的理論性能;而另一 些我們則只是根據經驗知道它們是可用的。
我們的主要目標是學習典型問題的各種有效算法,但也會注意比較不同算法之間的性能差異。不應該使用資源消耗情況未知的算法,因此我們會時刻關注 算法的期望性能。

Java 程序的基本結構
一段 Java 程序(類)或者是一個靜態方法(函數)庫,或者定義了一個數據類型。
要創建靜態 方法庫和定義數據類型,會用到下面七種語法,它們是 Java 語言的基礎,也是大多數現代語言所共有的 。

原始數據類型:它們在計算機程序中精確地定義整數、浮點數和布爾值等。它們的定義包括 取值范圍和能夠對相應的值進行的操作,它們能夠被組合為類似于數學公式定義的表達式。

語句:語句通過創建變量并對其賦值、控制運行流程或者引發副作用來進行計算。我們會使

用六種語句:聲明、賦值、條件、循環、調用和返回。
數組:數組是多個同種數據類型的值的集合。
靜態方法:靜態方法可以封裝并重用代碼,使我們可以用獨立的模塊開發程序。
字符串:字符串是一連串的字符,Java 內置了對它們的一些操作。
標準輸入 / 輸出:標準輸入輸出是程序與外界聯系的橋梁。
數據抽象:數據抽象封裝和重用代碼,使我們可以定義非原始數據類型,進而支持面向對象編程

典型的數組處理代碼
找出數組中最大的元素

double max = a[0]; for (int i = 1; i < a.length; i++)if (a[i] > max) max = a[i];

計算數組元素的平均值

int N = a.length; double sum = 0.0; for (int i = 0; i < N; i++)sum += a[i]; double average = sum / N;

復制數組

int N = a.length; double[] b = new double[N]; for (int i = 0; i < N; i++) b[i] = a[i];

顛倒數組元素的順序

int N = a.length;for (int i = 0; i < N/2; i++){double temp = a[i];a[i] = a[N-1-i];a[N-i-1] = temp; }

矩陣相乘(方陣) a[][] * b[][] = c[][]

int N = a.length; double[][] c = new double[N][N]; for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) { //計算行i和列j的點乘 for (int k = 0; k < N; k++)c[i][j] += a[i][k]*b[k][j]; }

計算一個整數的絕對值

public static int abs(int x) {if (x < 0) return -x;else return x; }

計算一個浮點數的絕對值

public static double abs(double x) {if (x < 0.0) return -x;else return x; }

判定一個數是否是素數 //一個大于1的自然數,且除了1和它本身外,不能被其他自然數整除的數叫素數

public boolean isPrime(int n){if (n < 2)return false;for (int i = 2; i*i < n; i++) {if (n%i==0)return false;}return true; }

計算平方根(牛頓迭代法)

public static double sqrt(double c) {if (c < 0) return Double.NaN;double err = 1e-15;double t = c;while (Math.abs(t - c / t) > err * t)t = (c / t + t) / 2.0;return t; }

計算直角三角形的斜邊

public static double hypotenuse(double a, double b) { return Math.sqrt(a*a + b*b); } 計算調和級數 public static double H(int N) {double sum = 0.0;for (int i = 1; i <= N; i++)sum += 1.0 / i;return sum; }

遞歸
方法可以調用自己(如果你對遞歸概念感到奇怪,請完成練習 1.1.16 到練習 1.1.22)
類型轉換
String值和數字之間相互轉換的API
parseInt(String s)
toString(int i)
parseDouble(String s)
toString(double x)
將字符串 s 轉換為整數 將整數 i 轉換為字符串
將字符串 s 轉換為浮點數 將浮點數 x 轉換為字符串

二分查找

public int search(int[] nums, int target) {int low = 0;int high = nums.length - 1;while (low < high) {int mid = (low + high) >> 1;if (nums[mid] == target) {return mid;} else if (nums[mid] > target) {high = mid - 1;} else if (nums[mid] < target) {low = mid + 1;}}return -low; }

問 什么是 Java 的字節碼?
答 它是程序的一種低級表示,可以運行于 Java 的虛擬機。將程序抽象為字節碼可以保證 Java 程序員的代碼能夠運行在各種設備之上

問 Java 允許整型溢出并返回錯誤值的做法是錯誤的。難道 Java 不應該自動檢查溢出嗎?
答 這個問題在程序員中一直是有爭議的。簡單的回答是它們之所以被稱為原始數據類型就是因為缺乏此類檢查。避免此類問題并不需要很高深的知識。我們會使用 int 類型表示較小的數(小于 10 個十進制位)而使用 long 表示 10 億以上的數。
問 Math.abs(-2147483648)的返回值是什么?
答 -2147483648。這個奇怪的結果(但的確是真的)就是整數溢出的典型例子
問 如何才能將一個 double 變量初始化為無窮大?
答 可以使用 Java 的內置常數:Double.POSITIVE_INFINITY 和 Double.NEGATIVE_INFINITY。
問 能夠將 double 類型的值和 int 類型的值相互比較嗎?
答 不通過類型轉換是不行的,但請記住 Java 一般會自動進行所需的類型轉換。例如,如果 x 的類型是 int 且值為 3,那么表達式 (x<3.1) 的值為 true——Java 會在比較前將 x 轉換為 double 類型(因為 3.1是一個 double 類型的字面量)。

問 如果使用一個變量前沒有將它初始化,會發生什么?
答 如果代碼中存在任何可能導致使用未經初始化的變量的執行路徑,Java 都會拋出一個編譯異常
問 Java 表達式 1/0 和 1.0/0.0 的值是什么?
答 第一個表達式會產生一個運行時除以零異常(它會終止程序,因為這個值是未定義的);第二個表 達式的值是 Infinity(無窮大)。

問 能夠使用 < 和 > 比較 String 變量嗎?
答 不行,只有原始數據類型定義了這些運算符。請見 1.1.2.3 節

問 負數的除法和余數的結果是什么?
答 表達式a/b的商會向0取整;a % b的余數的定義是(a/b)*b + a % b恒等于a。例如-14/3和14/-3的商都是-4,但-14 % 3是-2,而14 % -3是 2。

問 為什么使用(a && b)而非(a & b)?
答 運算符 &、| 和 ^ 分別表示整數的位邏輯操作與、或和異或。因此,10|6 的值為 14,10^6 的值為 12。在本書中我們很少(偶爾)會用到這些運算符。&& 和 || 運算符僅在獨立的布爾表達式中有效,原因是短路求值法則:表達式從左向右求值,一旦整個表達式的值已知則停止求值。
問 嵌套 if 語句中的二義性有問題嗎?
答 是的。在 Java 中,以下語句:
if if else 等價于:
if { if else }
即使你想表達的是:
if { if } else
避免這種“無主的”else 陷阱的最好辦法是顯式地寫明所有大括號

問 一個 for 循環和它的 while 形式有什么區別?
答 for循環頭部的代碼和for循環的主體代碼在同一個代碼段之中。在一個典型的for循環中,遞
增變量一般在循環結束之后都是不可用的;但在和它等價的 while 循環中,遞增變量在循環結束
之后仍然是可用的。這個區別常常是使用 while 而非 for 循環的主要原因

問 有些 Java 程序員用 int a[] 而不是 int[] a 來聲明一個數組。這兩者有什么不同?
答 在 Java 中,兩者等價且都是合法的。前一種是 C 語言中數組的聲明方式。后者是 Java 提倡的方式,因為變量的類型 int[] 能更清楚地說明這是一個整型的數組。

問 為什么數組的起始索引是 0 而不是 1 ?
答 這個習慣來源于機器語言,那時要計算一個數組元素的地址需要將數組的起始地址加上該元素的索引。將起始索引設為 1 要么會浪費數組的第一個元素的空間,要么會花費額外的時間來將索引減 1。

問 如果a[]是一個數組,為什么StdOut.println(a)打印出的是一個十六進制的整數,比如@f62373,而不是數組中的元素呢?
答 問得好。該方法打印出的是這個數組的地址,不幸的是你一般都不需要它。

問 我的程序能夠重新讀取標準輸入中的值嗎?
答 不行,你只有一次機會,就好像你不能撤銷 println() 的結果一樣

問 在 Java 中,一個靜態方法能夠將另一個靜態方法作為參數嗎?
答 不行,但問得好,因為有很多語言都能夠這么做 //?

判斷字符串是否是一條回文

public static boolean isPalindrome(String s) {int N = s.length();for (int i = 0; i < N / 2; i++)if (s.charAt(i) != s.charAt(N - 1 - i))return false;return true; }

從一個命令行參數中提取文件名和擴展名
String s = args[0];
int dot = s.indexOf(".");
String base = s.substring(0, dot);
String extension = s.substring(dot + 1, s.length());

檢查一個字符串數組中的元素是否已按照字母表順序排列//降序
public boolean isSorted(String[] a) {
for (int i = 1; i < a.length; i++) {
if (a[i - 1].compareTo(a[i]) > 0)
return false;
}
return true;
}

問 為什么要使用數據抽象?
答 它能夠幫助我們編寫可靠而正確的代碼
問 為什么要區別原始數據類型和引用類型?為什么不只用引用類型?
答 因為性能。Java 提供了 Integer、Double 等和原始數據類型對應的引用類型,以供希望忽略這些類型的區別的程序員使用。原始數據類型更接近計算機硬件所支持的數據類型,因此使用它們的程序比使用引用類型的程序運行得更快

問 數據類型必須是抽象的嗎?
答 不。Java 也支持 public 和 protected 來幫助用例直接訪問實例變量。如正文所述,允許用例代碼 直接訪問數據所帶來的好處比不上對數據的特定表示方式的依賴所帶來的壞處,因此我們代碼中所有的實例變量都是私有的(private),有時也會使用私有實例方法在公有方法之間共享代碼

問 指針是什么?
答 問得好。或許上面那個異常應該叫做 NullReferenceException。和 Java 的引用一樣,可以把指 針看做機器地址。在許多編程語言中,指針是一種原始數據類型,程序員可以用各種方法操作它。但眾所周知,指針的編程非常容易出錯,因此需要精心設計指針類的操作以幫助程序員避免錯誤
在 Java 中,創建引 用的方法只有一種(new),且改變引用的方法也只有一種(賦值語句)。也就是說,程序員能對引 用進行的操作只有創建和復制。
在編程語言的行話里,Java 的引用被稱為安全指針,因為 Java 能夠 保證每個引用都會指向某種類型的對象(而且它能找出無用的對象并將其回收)。習慣于編寫直接 操作指針的程序員認為 Java 完全沒有指針,但人們仍在為是否真的需要不安全的指針而爭論
問 我在哪里能夠找到 Java 如何實現引用和進行垃圾收集的細節?
答 Java 系統的實現各有不同。例如,實現引用的一種自然方式是使用指針(機器地址);而另一種使 用的則可能是句柄(指針的指針)。前者訪問數據的速度更快,而后者則能夠更好地實現垃圾回收
問 實現繼承有什么問題?
答 子類繼承阻礙模塊化編程的原因有兩點。
第一,父類的任何改動都會影響它的所有子類。子類的開發不可能和父類無關。事實上,子類是完全依賴于父類的。這種問題被稱為脆弱的基類問題。
第二, 子類代碼可以訪問所有實例變量,因此它們可能會扭曲父類代碼的意圖
什么是空(null)?
它是一個不指向任何對象的字面量。引用null調用一個方法是沒有意義的,并且會產生 NullPointerException。如果你得到了這條錯誤信息,請檢查并確認構造函數是否正確地初始化了類的所有實例變量

背包、隊列和棧
背包是一種不支持從中刪除元素的集合數據類型
先進先出隊列(或簡稱隊列)是一種基于先進先出(FIFO)策略的集合類型
下壓棧(或簡稱棧)是一種基于后進先出(LIFO)策略的集合類型

本節的第一個目標是說明我們對集合中的對象的表示方式將直接影響各種操作的效率。對于集合來說,我們將會設計適于表示一組對象的數據結構并高效地實現所需的方法。
本節的第二個目標是介紹泛型和迭代。它們都是簡單的 Java 概念,但能極大地簡化用例代碼。 它們是高級的編程語言機制,雖然對于算法的理解并不是必需的,但有了它們我們能夠寫出更加清晰、簡潔和優美的用例(以及算法的實現)代碼。
本節的第三個目標是介紹并說明鏈式數據結構的重要性,特別是經典數據結構鏈表,有了它我 們才能高效地實現背包、隊列和棧。理解鏈表是學習各種算法和數據結構中最關鍵的第一步
泛型
集合類的抽象數據類型的一個關鍵特性是我們應該可以用它們存儲任意類型的數據。一種特別的 Java 機制能夠做到這一點,它被稱為泛型,也叫做參數化類型
Evaluate
將操作數壓入操作數棧;
將運算符壓入運算符棧;
忽略左括號;
在遇到右括號時,彈出一個運算符,彈出所需數量的操作數,并將運算符和操作數的運算結果壓入操作數棧。

對增長數量級的常見假設的總結 //1.4.4

第2章 排 序
排序就是將一組對象按照某種邏輯順序重新排列的過程
即使你只是使用標準庫中的排序函數,學習排序算法仍然有三大實際意義:
‰ 對排序算法的分析將有助于你全面理解本書中比較算法性能的方法;
‰ 類似的技術也能有效解決其他類型的問題;
‰ 排序算法常常是我們解決其他問題的第一步。
更重要的是這些算法都很經典、優雅和高效

初級排序//選擇、插入
問 為什么有這么多排序算法? 答 原因之一是許多排序算法的性能都和輸入模型有很大的關系,因此不同的算法適用于不同應用場景中的不同輸入
歸并排序
即將兩個有序的數組歸并成一個更大 的有序數組
快速排序
它可能是應用最廣泛的排序算法了。快速排序流行的原因是它實現簡單、 適用于各種不同的輸入數據且在一般應用中比其他排序算法都要快得多。快速排序引人注目的特點包 括它是原地排序(只需要一個很小的輔助棧),且將長度為 N 的數組排序所需的時間和 NlgN 成正比
它的主要缺點是非常脆弱,在實現 時要非常小心才能避免低劣的性能。已經有無數例子顯示許多種錯誤都能致使它在實際中的性能只 有平方級別
性能特點
快速排序切分方法的內循環會用一個遞增的索引將數組元素和一個定值比較。這種簡潔性 也是快速排序的一個優點,很難想象排序算法中還能有比這更短小的內循環了。例如,歸并 排序和希爾排序一般都比快速排序慢,其原因就是它們還在內循環中移動數據
快速排序另一個速度優勢在于它的比較次數很少
快速排序的最好情況是每次都正好能將數組對半分。在這種情況下快速排序所用的比較次數正 好滿足分治遞歸的CN=2CN/2+N公式。2CN/2 表示將兩個子數組排序的成本,N表示用切分元素和所 有數組元素進行比較的成本
盡管快速排序有很多優點,它的基本實現仍有一個潛在的缺點:在切分不平衡時這個程序可能會 極為低效。例如,如果第一次從最小的元素切分,第二次從第二小的元素切分,如此這般,每次調用 只會移除一個元素。這會導致一個大子數組需要切分很多次。我們要在快速排序前將數組隨機排序的 主要原因就是要避免這種情況。它能夠使產生糟糕的切分的可能性降到極低,我們就無需為此擔心了
快速排序最多需要約 N 2/2 次比較,但隨機打亂數組能夠預防這種情況
三向切分的快速排序

優先隊列
第 3 章 查 找
二叉查找樹、紅黑樹和散列表

符號表
二叉查找樹
一種能夠將鏈表插入的靈活性和有序數組查找的高效性結合起來的符號表 實現
定義。一棵二叉查找樹(BST)是一棵二叉樹,其中每個結點都含有一個 Comparable 的鍵(以 及相關聯的值)且每個結點的鍵都大于其左子樹中的任意結點的鍵而小于右子樹的任意結點 的鍵。
平衡查找樹
紅黑二叉查找樹
一棵大小為 N 的紅黑樹的高度不會超過 2lgN
散列表
第4章 圖
定義。圖是由一組頂點和一組能夠將兩個頂點相連的邊組成的。
無向圖
二分圖//電影和演員的關系
第5章字符串
字符。String是由一系列字符組成的。字符的類型是char
不可變性。String 對象是不可變的
正則表達式
第6章背景
B- 樹
B- 樹的成本模型。我們使用頁的訪問次數(無論讀寫)作為外部查找算法的成本模型
B- 樹
它是對 3.3 節所述的 2-3 樹數據結構的擴展。關鍵的不同在于:我們不會將數據保存在樹中,而是會構造一棵由鍵的副本組成的樹,每個副本都關聯著一條鏈接。這種方式能夠更加方便地將索引和符號表本身分開,就像一本實體書中的索引一樣
線性規劃。給定一個由 M 個線性不等式組成的集合和含有 N 個決策變量的線性等式,以及一個由該 N 個決策變量組成的線性目標函數,找出能夠使目標函數的值最大化的一組變量值,或者證 明不存在這樣的賦值方案

總結

以上是生活随笔為你收集整理的算法-第四版的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。