數據結構及算法

數據結構是相互之間存在一種或多種特定關係的數據元素的集合(數據元素能夠由多個數據項構成,這種數據元素通常叫記錄,但數據元素必須屬於同一數據對象)。也能夠說:數據結構指同一類數據元素中,各元素之間的相互關係。數據結構由工業界誕生,具體的數據結構由具體的業務場景決定,人們從商業應用中某一類/某個數據對象的數據表現出來的邏輯關係來定義數據結構。java

根據數據元素之間關係的不一樣特性,一般有下列四種基本機構:1:集合,結構中的元素除了同屬一個數據對象外沒有其餘關係。2:線性結構(線性表),結構中的元素同屬一個數據對象,一個對一個首尾相連,有惟一的「第一個」數據元素和「最後一個」數據元素,相鄰元素存在順序不可打亂的關係。3:樹形結構(二叉樹),結構中的元素同屬一個數據對象,結構中的元素存在一個對多個的關係。4:圖狀結構/網狀結構,結構中的元素同屬一個數據對象,結構中的元素存在多個對多個的關係。數據結構描述的關係並非真正的邏輯關係,由於數據元素之間在數據內容上沒有具體邏輯可言,這種關係只是特定業務場景下對應的數據元素集合內數據元素間的存在關係。算法

數據結構的形式定義爲:數據結構是一個二元組數組

Data_Structure=(D,S);數據結構

D是數據元素的有限集,S是數據元素間關係的有限集函數

數據類型和數據結構的概念密切相關,數據類型是一個值的集合和定義在這個值集上的一組操做的總稱(包含了「集合」這種數據結構和一組操做)。設計

數據類型的三元組表示形式爲:指針

(D,S,P)code

D是數據元素的有限集,S是數據元素間關係的有限集,P是對數據元素的操做集。對象

數據結構在計算機中的表示/映像稱爲數據元素的物理結構,又稱存儲結構,包括數據元素的表示和存在關係的表示。blog

數據的存在關係結構和物理結構是密切相關的,任何一個算法的設計取決於存在關係結構,算法的實現依賴於採起的存儲結構。

數據元素之間的存在關係在計算機中有兩種不一樣的表示方法:順序映像和非順序映像,並由此獲得兩種不一樣的存儲結構:順序存儲結構和鏈式存儲結構。(四種數據結構(存在關係)能夠用兩種物理結構的任意一種來表示)

順序映像的特色是:藉助元素在存儲器中的相對位置來表示數據元素之間的存在關係。好比用兩個字長的位串來表示一個實數,則能夠用地址相鄰的四個字長的位串表示一個複數。

非順序映像的特色是:藉助指示存儲元素地址的指針來表示數據元素之間的存在關係。見下圖(b)

                                                                         線性表/線性結構

線性結構(線性表),結構中的元素同屬一個數據對象,一個對一個首尾相連,有惟一的「第一個」數據元素和「最後一個」數據元素,相鄰元素存在順序不可打亂的關係。第一個數據元素的地址常稱爲起始位置或基地址。含有大量記錄(含有多個數據項的數據元素)的線性表又稱爲文件。

順序存儲結構和鏈式存儲結構表示線性表/線性結構:

順序存儲結構

插入或刪除元素成本大:順序存儲結構中,在某個位置上插入或刪除一個數據元素時,時間主要消耗在移動元素上,移動元素的個數取決於插入或刪除元素的位置。

可隨機存(set賦值)取(get讀值):順序存儲結構中,每一個元素的存儲位置和物理結構表示的線性表的起始位置相差一個和數據元素在線性表中位置成正比的常數,只要肯定了起始位置即可存取任一元素。

(高級程序語言中經常用數組來描述順序存儲結構。)

鏈式存儲結構

用一組任意的存儲單元存儲線性表的數據元素,所以爲了表示每一個數據元素和其直接後繼元素的邏輯關係,元素a的存儲映像除了保存元素的數據信息外還需存儲一個指示其直接後繼元素位置的信息,元素的這個存儲映像也稱爲結點,包括數據域和指針域。

C語言中的指針和java中的對象引用是一個意思。

每一個結點中只包含一個指針域,這樣的鏈式存儲結構也叫線性鏈表或單鏈表。最後一個元素沒有後繼元素,所以線性鏈表的最後一個結點的指針爲null。

整個鏈表的存取(set、get)必須從頭指針開始進行。

整個鏈表的插入或刪除僅須要修改最多兩個指針不須要移動元素。

 

任何一種數據結構:起始位置是系統肯定的,插入的數據必定能夠是有序的,雖然set沒有實現。

關於雙向鏈表和循環鏈表:

循環鏈表即收尾相連的鏈表,最後一個元素的指針部分指出第一個元素的存儲位置。

雙向鏈表則是指元素的指針部分有兩塊,一塊指向前趨元素,一塊指向後繼元素。雙向鏈表也能夠是循環的(確定是能夠的,工業界各類結構可見,而數據結構課程是對工業界數據結構的總結)。

 

 

                                                                                     

 

                                                                                     線性表/線性結構之數組

數組是受限的線性結構

數組一旦被定義其維數和維界再也不改變,所以除告終構的初始化和銷燬外,數組只有存取元素和修改元素值的操做,不能插入和刪除。所以,採用順序存儲結構表示數組是天然的事了(也能夠用鏈式結構)。在java語言中數組類型數據的確是不可變長的,但用數組實現的arrayLis和Vector都可以在指定位置刪除和插入元素,本質是創建一個新的數組而後進行復制。

                                                                                    線性表/線性結構之棧和隊列

棧和隊列也是受限的線性表結構,棧和隊列同樣能夠用鏈式結構和順序結構來表示。順序棧(順序存儲結構的棧)設立一個top指針來指示棧頂元素,出棧時top指針減1,入棧則加1.

隊列和棧相似,指示須要在隊頭和隊尾設立兩個指針。

 

                                                                                      樹和二叉樹

樹是n個節點的有限集,任何非空樹中有且僅有一個根節點。n>1時,其餘節點可分爲若干個互不相交的有限集,每一個集合自己是一個樹,稱爲根的子樹。

樹的節點包含一個數據元素和若干指向其子樹的分支,節點擁有的子樹的數量稱爲子樹的度。度爲0的節點稱爲葉子或終端節點。節點A的子樹的根節點B稱爲節點A的孩子,反過來節點A是節點B的雙親。同一雙親的孩子稱爲兄弟。

樹中節點的最大層次爲數的深度(第一層爲根節點,最後一層爲葉子)。

若是將樹種各子樹當作是有序的則爲有序樹,不然爲無序樹,有序樹中左邊第一個子樹爲第一個孩子,右邊第一個子樹爲最後一個孩子。任意一個節點至多隻有兩個分支而且子樹有左右之分的樹稱爲二叉樹(二叉樹中不存在度大於2的節點),(任何二叉樹都是有序樹)

一個深度爲k且有(2的k次方)-1個節點的二叉樹爲滿二叉樹。

將一個滿二叉樹編號,從上至下,從左到右。若是一個普通二叉樹上的節點跟滿二叉樹上對應位置的節點的編號同樣,則該二叉樹爲徹底二叉樹。

二叉樹的存儲結構:

順序存儲結構只適用於徹底二叉樹(非徹底二叉樹的空節點隨機分佈且編號不肯定)

鏈式存儲結構:由二叉樹的定義知一個結點至少包括數據,左右指針,有時還包括指向雙親的指針,根據這兩種結構獲得二叉樹的物理存儲結構爲二叉鏈表和三叉鏈表。二叉鏈表查找某節點只能從根節點出發。

二叉樹的遍歷和線索二叉樹:

在實際應用中對二叉樹遍歷是少不了的操做,爲了方便對二叉樹進行遍歷,必須在第一次複雜的遍歷的動態過程當中對二叉樹進行線索化(第一次遍歷按照樹上全部根節點統一被遍歷的前後順序分爲先序遍歷,中序遍歷和後序遍歷),將線性遍歷鏈路上的每一個節點可找到其前趨和後繼元素,以便之後實現簡單的線性遍歷。這個過程叫二叉樹的線索化,線索化後的二叉樹叫線索二叉樹。固然線索二叉樹上有左右子樹的節點是沒有後繼/前趨元素的,線索二叉樹在遍歷到這類節點的時候按照先序/中序/後序原則找到其後繼元素繼續進行遍歷。

二叉樹和二叉排序樹的區別:二叉樹是隻區分左右子樹的有序樹,而二叉排序樹則分清了左右子樹的值和節點的值相比較的大小。

 

                                                                                     查找

查找和存取的區別?

根據相對於起始元素的相對位置進行的搜尋叫存取,根據內容(關鍵字)進行的搜尋叫查找。順序存儲結構的存取能夠根據相對於起始元素的相對位置算出目標元素的地址進行直接存取,鏈式存儲結構的存取只能從特殊位置出發一個一個找(單鏈表只能從頭,雙向鏈表只能頭/尾,雙向循環鏈表能夠任何一個元素,線索二叉樹若是用二叉鏈表只能從根節點,三叉鏈表是根節點或最後一個遍歷的節點)。java語言沒有提供對非順序存儲結構的集合中單個元素的存取(只能add添加一個元素和遍歷取得全部元素)。

實際應用中有一種大量使用的集合性質的集合元素間沒有存在關係(除了同屬一個數據對象),徹底鬆散的數據結構——"查找表"。

對查找表常進行的操做有:1,查詢某數據元素是否在查找表中2,檢索某數據元素的各類屬性3,在查找表中插入元素4,在查找表中刪除元素。只對查找表進行前兩種操做時稱該查找表爲靜態查找表,對查找表的操做包括插入和刪除元素時稱該查找表爲動態查找表。

關鍵字(key):關鍵字是數據元素(或記錄)中某個數據項的值,它能夠標識一個數據元素或記錄,若關鍵字能夠惟一得標識一個記錄則該關鍵字爲主關鍵字,不然爲次關鍵字。關鍵字的概念不只用於集合,在四種邏輯結構中也用於線性結構(如線性表)和樹形結構。關鍵字只是數據的一部分,僅僅和數據有關係,和數據元素的位置沒有任何關係。給出關鍵字找到對應數據只能經過讓全部數據元素的關鍵字和給定的關鍵字依次比較來查找,查找的快慢取決於比較的次數。。。

查找:根據給定的某個值,在查找表中肯定一個其關鍵字等於給定值的數據元素或記錄的過程即查找。

 

靜態查找表查找方法通常有順序表查找(實現順序查找意味着必須將查找表進行線性化遍歷,用線性結構實現或以二叉鏈表或三叉鏈表來實現再進行線索化,而後實現順序查找,但這樣更麻煩。說白了順序表查找就是一個一個找。)和有序表的折半查找。折半查找只適用於順序存儲結構(存儲位置須要折半),而且元素也是按大小順序排列的才行。靜態查找表中查找效率幾乎最高構建成本又不高的結構是次優二叉查找樹。次優二叉查找樹和後面所說的二叉排序樹惟一的區別是靜態的,不能刪除或添加元素,根據固定的元素一次性生成。而且次優二叉查找樹取的根節點不是按數據大小的中間值取的,而是取最接近給定值的元素爲根節點。 

從靜態查找表的查找方法能夠看出最適合實現查找的物理存儲結構是樹結構,根據範圍邊界來排查查找無疑提升了查找效率。還有一種更高效率的查找方式是哈希表(但哈希表的構建成本應該高,索引都不用哈希表去實現可想而知。。。) 

  

二叉排序樹:

對於任何一個結點,左子樹的值均小於根節點的值,右子樹的值均大於根節點的值。而且二叉排序樹是動態生成的,一個元素一個元素查找並添加且不添加劇復元素。

二叉排序樹的查找:

先比較根節點的值,再依次從左子樹/右子樹進行查找。

二叉排序樹的插入或刪除:

插入:當樹中不存在關鍵字等於給定值的節點時再進行插入。

刪除P節點時:用P節點的左子樹替代P,並將P節點的右子樹變成P節點左子樹的最右節點的右子樹。

平衡二叉樹:

任何一個節點的左子樹深度減去右子樹的深度的絕對值小於等於1.平衡二叉樹不必定是二叉排序樹,討論是不是平衡二叉樹僅關注深度。

B-樹和B+樹:

B-樹幾乎和二叉排序樹如出一轍,僅僅是分叉多了而已。查找過程也如出一轍。

B+樹是B-樹的變形,差別僅在於:1.每一個節點上的關鍵字和其子樹數量相等(B-樹中關鍵字爲子樹個數-1)。2.葉子節點包含所有關鍵字的信息並依關鍵字大小從小到大順序連接(比B-樹多了一種查找方式)3.結點中的關鍵字是子樹中的最大/最小關鍵字。

 

                                                                                    哈希表

在線性表和樹中,記錄在結構中的相對位置是隨機的,和記錄的關鍵字之間不存在肯定的關係,所以在結構中查找記錄時需進行一系列和關鍵字的比較,查找的效率取決於查找過程當中所進行的比較次數。理想的狀況是但願不進行任何比較,一次獲得所查記錄,那就必須在記錄的存儲位置和它的關鍵字之間創建一個肯定的對應關係,是每一個關鍵字和結構中一個惟一的存儲位置相對應。咱們稱這個對應關係f爲哈希函數,哈希函數是關鍵字集合到地址集合的映像。按這個思想創建的表爲哈希表。

哈希表只能代表查找方式,不能說明底層物理存儲結構是以什麼實現的。

由此可知:hashset和treeset的本質區別是查找數據元素時的效率:前者直接根據哈希code定位到數據元素的地址,後者是根據節點關鍵字肯定範圍排除查找關鍵字。

                  插入數據方面的區別彷佛沒有:由於hashset也須要遍歷集合來保證其中沒有相同的hashcode。treeset暫不詳,只知道排序二叉樹樹和hashset的插入是同樣的,只是遍歷的不是hashcode而是關鍵字而已。

 

 

 

 

 

 

 

                                                                                 算法

算法是對特定問題的求解步驟的描述,是指令的有限序列。由控制結構(順序,分支,循環)和原子操做構成。一般以原操做重複執行的次數爲算法的時間度量。好比:

{++x;s=0}

算法複雜度爲O(1)

for(i=0;i<n;i++){++x;s+=x;}

算法複雜度爲O(n)

排序類算法關鍵:區分出嵌套循環,獨立循環和交叉循環(這一步映像作不到,算法基礎再好都扯淡)。交叉循環的自增一般放在交叉結果後。

冒泡排序:不斷比較取最大/小的值,便能把最大/小的值排到末尾。

構造哈希函數:對於關鍵字中的任何一個關鍵字,經哈希函數映像到地址集合中任何一個地址的機率是相等的,則成此類哈希函數是均勻的哈希函數。也就是讓關鍵字通過哈希函數獲得一個「隨機的地址」,以便使一組關鍵字的哈希地址均勻分佈在整個地址區間中,從而減小衝突。

1.直接定址法:一次線性關係

2.隨機數法:用一個隨機函數,取關鍵字的隨機函數值爲地址。

哈希衝突處理方法:

1:開放定址法:

2:再哈希法:產生哈希衝突時計算另外一個哈希函數地址,直到衝突再也不發生。

3:鏈地址法:

4:公共溢出區:創建一個公共溢出區,將產生衝突的哈希地址填入溢出表。

算法的複雜度:

 

                                                                                        內部排序

按排序工做量的分:1.簡單排序方法O(n²),   2.先進排序方法O(nlogn)   3.基數排序時間複雜度爲O(d▪n)

相關文章
相關標籤/搜索