(三) 數據結構

1.常用數據結構簡介

答:

1.幾個基本概念

數據:數據是指計算機接受的輸入數據,比如:整型、浮點型等數值類型以及聲音、圖像、視頻等非數值類型的數據

數據元素:是組成數據有一定意義的基本單位,比如一個人的基本信息包括姓名、性別、年齡等

數據對象:是性質相同的數據元素的集合,比如正整數數據對象N={1,2,3……}

數據結構:是數據的組織形式,即數據元素之間存在的一種或幾種特定關系

數據類型:是用來刻畫一組性質相同的數據及其上的操作。可以分為原子類型和結構類型。

抽象數據類型:對具有某種邏輯關系的數據類型進行描述,并在該類型上進行的一組操作。比如C++中的結構體。

2、數據結構

數據結構的主要任務就是通過描述對象的結構特征,包括邏輯結構在內的聯系,然后把邏輯結構表示成計算機可實現的物理結構,從而方便計算機處理。

邏輯結構:數據對象中數據元素之間的相互關系,即數據對象中的數據元素的所有分布情況滿足的規律。

集合結構:這種結構中的數據元素除了屬于同一數據對象之外沒有其他的任何關系。

線性結構:線性結構中的數據元素之間是一對一的關系,并且有一種先后次序關系。包括數組、線性表、棧、隊列和串等等。

樹形結構:樹形結構中的數據元素之間是一對多的層次關系。

圖形結構:圖形結構中的數據元素之間是多對多的關系。

2.物理結構:又稱存儲結構,指的是邏輯結構在計算機中的存儲形式。

順序存儲結構:把數據元素存放到地址連續的存儲單元里,數據間的邏輯關系和物理關系一致

鏈式存儲結構:把數據元素存放到任意的存儲單元里,地址可以不連續,通過指針實現數據元素之間的邏輯關系。

3、算法

算法的定義:描述解決問題的方法。使用不同的數據結構解決某一類或者具體的問題的策略。

算法的特性:

有窮性:算法執行有限的步驟之后會結束而不會出現無限循環。

確定性:對于相同的輸入只有唯一的輸出結果。

可行性:算法的每一步都必須在有限執行次數完成。

輸入:算法有零個輸入或多個輸入。

輸出:至少有一個或多個輸出。


2.列舉java的集合以及集合之間的繼承關系


用于存儲數據的容器。

特點:

1:對象封裝數據,對象多了也需要存儲。集合用于存儲對象。

2:對象的個數確定可以使用數組,但是不確定怎么辦?可以用集合。因為集合是可變長度的。


集合和數組的區別:

1:數組是固定長度的;集合可變長度的。

2:數組可以存儲基本數據類型,也可以存儲引用數據類型;集合只能存儲引用數據類型。

3:數組存儲的元素必須是同一個數據類型;集合存儲的對象可以是不同數據類型。

?

數據結構:就是容器中存儲數據的方式。


對于集合容器,有很多種。因為每一個容器的自身特點不同,其實原理在于每個容器的內部數據結構不同。

集合容器在不斷向上抽取過程中。出現了集合體系。

在使用一個體系時,原則:參閱頂層內容。建立底層對象。

?

------------------------------------------------------------

--< java.util >--?Collection接口:

Collection

??? |--List:有序(元素存入集合的順序和取出的順序一致),元素都有索引。元素可以重復。

??? |--Set:無序(存入和取出順序有可能不一致),不可以存儲重復元素。必須保證元素唯一性。


1,添加:

??? add(object):添加一個元素

addAll(Collection)?:添加一個集合中的所有元素。

2,刪除:

??? clear():將集合中的元素全刪除,清空集合

remove(obj)?:刪除集合中指定的對象。注意:刪除成功,集合的長度會改變。

removeAll(collection)?:刪除部分元素。部分元素和傳入Collection一致。

3,判斷:

boolean contains(obj)?:集合中是否包含指定元素 。

boolean containsAll(Collection)?:集合中是否包含指定的多個元素。

??? boolean isEmpty():集合中是否有元素。

4,獲取:

??? int size():集合中有幾個元素。

5,取交集:

boolean? retainAll(Collection)?:對當前集合中保留和指定集合中的相同的元素。如果兩個集合元素相同,返回flase;如果retainAll修改了當前集合,返回true。

6,獲取集合中所有元素:

?Iteratoriterator()迭代器

7,將集合變成數組:

toArray();

------------------------------------------------------------

--< java.util >--?Iterator接口:

迭代器:是一個接口。作用:用于取集合中的元素。

booleanhasNext()如果仍有元素可以迭代,則返回?true。

?Enext()返回迭代的下一個元素。

voidremove()從迭代器指向的?collection?中移除迭代器返回的最后一個元素(可選操作)。


每一個集合都有自己的數據結構,都有特定的取出自己內部元素的方式。為了便于操作所有的容器,取出元素。將容器內部的取出方式按照一個統一的規則向外提供,這個規則就是Iterator接口

也就說,只要通過該接口就可以取出Collection集合中的元素,至于每一個具體的容器依據自己的數據結構,如何實現的具體取出細節,這個不用關心,這樣就降低了取出元素和具體集合的耦合性。


Iterator it = coll.iterator();//獲取容器中的迭代器對象,至于這個對象是是什么不重要。這對象肯定符合一個規則Iterator接口。

-----------------------------------------------------------------------------

public static void main(String[] args) {

Collection coll = new ArrayList();

coll.add("abc0");

coll.add("abc1");

coll.add("abc2");

??????? //--------------方式1----------------------

Iterator it = coll.iterator();

while(it.hasNext()){

System.out.println(it.next());

}

??????? //---------------方式2用此種----------------------

?for(Iterator it = coll.iterator();it.hasNext(); ){

System.out.println(it.next());

}

}

-----------------------------------------------------------------------------

--< java.util >--?List接口:

List本身是Collection接口的子接口,具備了Collection的所有方法。現在學習List體系特有的共性方法,查閱方法發現List的特有方法都有索引,這是該集合最大的特點。


List有序(元素存入集合的順序和取出的順序一致),元素都有索引。元素可以重復。

?|--ArrayList底層的數據結構是數組,線程不同步,ArrayList替代了Vector,查詢元素的速度非常快。

?|--LinkedList底層的數據結構是鏈表,線程不同步,增刪元素的速度非常快。

?|--Vector底層的數據結構就是數組,線程同步的,Vector無論查詢和增刪都巨慢。


1,添加:

add(index,element)?:在指定的索引位插入元素。

addAll(index,collection)?:在指定的索引位插入一堆元素。

2,刪除:

remove(index)?:刪除指定索引位的元素。 返回被刪的元素。

3,獲取:

Object get(index)?:通過索引獲取指定元素。

int?indexOf(obj)?:獲取指定元素第一次出現的索引位,如果該元素不存在返回-1;

?所以,通過-1,可以判斷一個元素是否存在。

int lastIndexOf(Object o)?:反向索引指定元素的位置。

List?subList(start,end)?:獲取子列表。

4,修改:

Object set(index,element)?:對指定索引位進行元素的修改。

5,獲取所有元素:

ListIterator?listIterator():list集合特有的迭代器。


List集合支持對元素的增、刪、改、查。


List集合因為角標有了自己的獲取元素的方式: 遍歷。

for(int x=0; x

sop("get:"+list.get(x));

}

在進行list列表元素迭代的時候,如果想要在迭代過程中,想要對元素進行操作的時候,比如滿足條件添加新元素。會發生.ConcurrentModificationException并發修改異常。

導致的原因是:

集合引用和迭代器引用在同時操作元素,通過集合獲取到對應的迭代器后,在迭代中,進行集合引用的元素添加,迭代器并不知道,所以會出現異常情況。

如何解決呢?

既然是在迭代中對元素進行操作,找迭代器的方法最為合適.可是Iterator中只有hasNext,next,remove方法.通過查閱的它的子接口,ListIterator,發現該列表迭代器接口具備了對元素的增、刪、改、查的動作。


ListIteratorList集合特有的迭代器

ListIterator it = list.listIterator;//取代Iterator it = list.iterator;

方法摘要

voidadd(Ee)?將指定的元素插入列表(可選操作)。

booleanhasNext()?以正向遍歷列表時,如果列表迭代器有多個元素,則返回?true(換句話說,如果?next返回一個元素而不是拋出異常,則返回?true)。

booleanhasPrevious()?如果以逆向遍歷列表,列表迭代器有多個元素,則返回?true。

?Enext()?返回列表中的下一個元素。

intnextIndex()?返回對next?的后續調用所返回元素的索引。

?Eprevious()?返回列表中的前一個元素。

intpreviousIndex()?返回對previous?的后續調用所返回元素的索引。

voidremove()?從列表中移除由?next?或previous?返回的最后一個元素(可選操作)。

voidset(Ee)?用指定元素替換?next?或previous?返回的最后一個元素(可選操作)。


可變長度數組的原理:

當元素超出數組長度,會產生一個新數組,將原數組的數據復制到新數組中,再將新的元素添加到新數組中。

ArrayList:是按照原數組的50%延長。構造一個初始容量為?10?的空列表。

Vector:是按照原數組的100%延長。


注意:對于list集合,底層判斷元素是否相同,其實用的是元素自身的equals方法完成的。所以建議元素都要復寫equals方法,建立元素對象自己的比較相同的條件依據。


LinkedList的特有方法。

addFirst();

addLast();

在jdk1.6以后。

offerFirst();

offerLast();


getFirst():獲取鏈表中的第一個元素。如果鏈表為空,拋出NoSuchElementException;

getLast();

在jdk1.6以后。

peekFirst();獲取鏈表中的第一個元素。如果鏈表為空,返回null。

peekLast();


removeFirst():獲取鏈表中的第一個元素,但是會刪除鏈表中的第一個元素。如果鏈表為空,拋出NoSuchElementException

removeLast();

在jdk1.6以后。

pollFirst();獲取鏈表中的第一個元素,但是會刪除鏈表中的第一個元素。如果鏈表為空,返回null。

pollLast();

------------------------------------------------------------

--< java.util >--?Set接口

Set接口中的方法和Collection中方法一致的。Set接口取出方式只有一種,迭代器

?|--HashSet底層數據結構是哈希表,線程是不同步的無序,高效;

?HashSet集合保證元素唯一性:通過元素的hashCode方法,和equals方法完成的。

?當元素的hashCode值相同時,才繼續判斷元素的equals是否為true。

?如果為true,那么視為相同元素,不存。如果為false,那么存儲。

?如果hashCode值不同,那么不判斷equals,從而提高對象比較的速度。

?|--LinkedHashSet有序,hashset的子類。

?|--TreeSet對Set集合中的元素的進行指定順序的排序。不同步。TreeSet底層的數據結構就是二叉樹。


哈希表的原理:

1,對對象元素中的關鍵字(對象中的特有數據),進行哈希算法的運算,并得出一個具體的算法值,這個值 稱為哈希值

2,哈希值就是這個元素的位置。

3,如果哈希值出現沖突,再次判斷這個關鍵字對應的對象是否相同。如果對象相同,就不存儲,因為元素重復。如果對象不同,就存儲,在原來對象的哈希值基礎?+1順延。

4,存儲哈希值的結構,我們稱為哈希表。

5,既然哈希表是根據哈希值存儲的,為了提高效率,最好保證對象的關鍵字是唯一的。

?這樣可以盡量少的判斷關鍵字對應的對象是否相同,提高了哈希表的操作效率。


對于ArrayList集合,判斷元素是否存在,或者刪元素底層依據都是equals方法。

對于HashSet集合,判斷元素是否存在,或者刪除元素,底層依據的是hashCode方法和equals方法。


TreeSet:

?用于對Set集合進行元素的指定順序排序,排序需要依據元素自身具備的比較性。

?如果元素不具備比較性,在運行時會發生ClassCastException異常。

?所以需要元素實現Comparable接口,強制讓元素具備比較性,復寫compareTo方法

?依據compareTo方法的返回值,確定元素在TreeSet數據結構中的位置。

?TreeSet方法保證元素唯一性的方式:就是參考比較方法的結果是否為0,如果return 0,視為兩個對象重復,不存。


注意:在進行比較時,如果判斷元素不唯一,比如,同姓名,同年齡,才視為同一個人。

?在判斷時,需要分主要條件和次要條件,當主要條件相同時,再判斷次要條件,按照次要條件排序。


TreeSet集合排序有兩種方式,ComparableComparator區別:

1:讓元素自身具備比較性,需要元素對象實現Comparable接口,覆蓋compareTo方法。

2:讓集合自身具備比較性,需要定義一個實現了Comparator接口的比較器,并覆蓋compare方法,并將該類對象作為實際參數傳遞給TreeSet集合的構造函數。

第二種方式較為靈活。


------------------------------------------------------------

Map集合:

|--Hashtable底層是哈希表數據結構,是線程同步的。不可以存儲null鍵,null值。

|--HashMap底層是哈希表數據結構,是線程不同步的。可以存儲null鍵,null值。替代了Hashtable.

|--TreeMap底層是二叉樹結構,可以對map集合中的鍵進行指定順序的排序。

?

Map集合存儲和Collection有著很大不同:

Collection一次存一個元素;Map一次存一對元素。

Collection是單列集合;Map是雙列集合。

Map中的存儲的一對元素:一個是鍵,一個是值,鍵與值之間有對應(映射)關系。

特點:要保證map集合中鍵的唯一性。


1,添加。

put(key,value):當存儲的鍵相同時,新的值會替換老的值,并將老值返回。如果鍵沒有重復,返回null。

void?putAll(Map);

2,刪除。

void?clear():清空

value?remove(key)?:刪除指定鍵。

3,判斷。

boolean?isEmpty():

boolean?containsKey(key):是否包含key

boolean?containsValue(value)?:是否包含value

4,取出。

int?size():返回長度

value?get(key)?:通過指定鍵獲取對應的值。如果返回null,可以判斷該鍵不存在。當然有特殊情況,就是在hashmap集合中,是可以存儲null鍵null值的。

Collection?values():獲取map集合中的所有的值。

5,想要獲取map中的所有元素:

?原理:map中是沒有迭代器的,collection具備迭代器,只要將map集合轉成Set集合,可以使用迭代器了。之所以轉成set,是因為map集合具備著鍵的唯一性,其實set集合就來自于map,set集合底層其實用的就是map的方法。

★?map集合轉成set的方法:

Set keySet();

Set entrySet();//取的是鍵和值的映射關系。

Entry就是Map接口中的內部接口;

為什么要定義在map內部呢?entry是訪問鍵值關系的入口,是map的入口,訪問的是map中的鍵值對。


3.數組和鏈表的區別

答:

數組是將元素在內存中連續存放,由于每個元素占用內存相同,可以通過下標迅速訪問數組中任何元素。但是如果要在數組中增加一個元素,需要移動大量元素,在內存中空出一個元素的空間,然后將要增加的元素放在其中。同樣的道理,如果想刪除一個元素,同樣需要移動大量元素去填掉被移動的元素。如果應用需要快速訪問數據,很少或不插入和刪除元素,就應該用數組。

鏈表恰好相反,鏈表中的元素在內存中不是順序存儲的,而是通過存在元素中的指針聯系到一起。比如:上一個元素有個指針指到下一個元素,以此類推,直到最后一個元素。如果要訪問鏈表中一個元素,需要從第一個元素開始,一直找到需要的元素位置。但是增加和刪除一個元素對于鏈表數據結構就非常簡單了,只要修改元素中的指針就可以了。如果應用需要經常插入和刪除元素你就需要用鏈表數據結構了

? ?綜合以上,對于快速訪問數據,不經常有添加刪除操作的時候選擇數組實現,而對于經常添加刪除數據,對于訪問沒有很高要求的時候選擇鏈表。


?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,702評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,615評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,606評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,044評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,826評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,227評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,307評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,447評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,992評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,807評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,001評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,550評論 5 361
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,243評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,667評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,930評論 1 287
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,709評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,996評論 2 374

推薦閱讀更多精彩內容