什么是數據結構?
♦ ♦ 講的還是數據之間的關系,簡單地說,數據結構是以某種特定的布局方式存儲數據的容器。這種“布局方式”決定了數據結構對於某些操作是高效的,而對於其他操作則是低效的。
①《數據結構與算法分析》一書中的定義是:“數據結構是 ADT(抽象數據類型Abstract Data Type) 的物理實現。”
② 數據結構包括數據對象集以及它們在計算機中的組織方式,即它們的邏輯結構和物理存儲結構,同時還包括與數據對象集相關的操作集,以及實現這些操作的最高效的算法。
③ 個人:就是把圖書館中的書轉化為一些字符數據存入電腦中,以及對這些數據對象集的操作。如找書,擺放、放書等。
邏輯結構:數據的邏輯結構就是數據之間關系,如順序關系,隸屬關系等
抽象數據類型:又叫引用數據類型,泛指除基本數據類型以外的數據類型,可以實例化的,具有屬性和方法。
抽象數據類型是由若干基本數據類型歸並之后形成的一種新的數據類型,這種類型由用戶定義,功能操作比基本數據類型更多,一般包括結構體和類。其實說白了,抽象數據類型就是把一些有一定關聯的基本數據類型打包,然后當做新的數據類型使用。其實實體類也是,可以調用其中的setter,getter方法。
什么是算法?
算法是在有限步驟內求解某一問題所使用的一組定義明確的規則。
通俗點說,就是計算機解題的過程。 在這個過程中,無論是形成解題思路還是編寫程序,都是在實施某種算法。 前者是推理實現的算法,后者是操作實現的算法。
數據結構關算法什么事?
例一: 計算機對弈(下五子棋)
算法:?對弈的規則和策略
模型(數據結構):?棋盤棋子的表示
例二: 超級瑪麗
操作方向左上右下,計算機是0或1,所以需要對左上右下建立相應的模型。不能光計算,還要有模型,有了模型才能更好地去計算,去
解決現實世界的問題。
邏輯結構 >>數據對象中數據元素之間的相互關系
圖形結構 樹形結構 線性結構 集合結構
物理結構(存儲結構)
1. 順序存儲結構(圖書館占一排9個座位) ArrayList源碼分析
指的是用一段地址連續的存儲單元依次存儲線性表的數據元素
優點:
-
不用為表示節點間的邏輯關系而增加額外的存儲開銷。
-
具有按元素序號隨機訪問的特點。
缺點:
-
在做插入/刪除操作時,平均每次移動表中的一半元素,因此表中數據量越大效率越低。
-
需要預先分配足夠大的存儲空間。過大可能會導致存儲空間閑置,過小會造成溢出。
使用:
- 線性表的長度變化不大,且其主要操作是查找。
2. 鏈式存儲結構(對不起,我是警察)
在計算機中用一組任意的存儲單元存儲線性表的數據元素(這組存儲單元可以是連續的,也可以是不連續的).
優點:
-
插入/刪除方便(只需要修改指針)。
缺點:
-
要占用額外的存儲空間存儲元素之間的關系,存儲密度低。
-
不是隨機存儲結構,不能隨機存取元素,只能順序存取。
使用:
- 線性表的長度變化較大,且其主要操作是插入/刪除。
【數據結構】節點和結點,到底怎么區分?
要記住:一般算法中點的都是結點。我們在數據結構的圖形表示中,對於數據集合中的每一個數據元素用中間標有元素值的方框表示,一般稱它為數據結點,簡稱結點。
在鏈表數據結構中,鏈表中每一個元素稱為“結點”,每個結點都應包括兩個部分:一個是需要用的實際數據data;另一個就是存儲下一個結點地址的指針,即數據域和指針域。
數據結構中的每一個數據結點對應於一個存儲單元,這種儲存單元稱為儲存結點,也可簡稱結點。
鏈表
結點由存放元素的數據域和存放后繼結點地址的指針域組成。
ai | ai+1 :結點/元素
p->next : 是一個指針(在java里就是引用),代表p的下一個結點
p->data | p->next->data : 結點的數據
前面的指針域存放的是后面結點的地址
在java里,p是對象,next是另一個對象。
public class P{ Object data;數據域,不關心是什么類型 //指針(java中是引用類型) c語言:指向下一個元素 java:引用下一個元素
P next;
}
P p1 = new P();
p1.data = "Danny"; P p2 = new P();
p1.next = p2;//表示p2是p1的next
單向鏈表
在鏈表結構中,每個結點僅本身需要存儲的數據和下一個節點地址的這種鏈表結構,我們稱為單鏈表結構,其示意圖如下:
如圖所示,在單鏈表中的每個節點中,除了數據區域外,還有一個區域存儲了當前節點的下一節點的地址,我們把這個記錄下個結點地址的指針或引用叫作后繼指針或引用Next。
在我們的單鏈表結構中,有兩個節點比較特殊,那就是第一個節點和最后一個節點。在鏈式存儲結構中,我們將第一個節點稱為頭結點,將最后一個節點稱為尾節點。
頭節點記錄鏈表的起始地址,有了這個地址,我們就可以遍歷整個鏈表。尾節點的后繼指針或者引用不是指向一個具體的節點,而是指向一個空地址NULL,從而表示該節點為鏈表的尾節點。
與數組一樣,鏈表也支持數據的插入、查找、刪除。
但是我們都知道,數組在進行數據的插入,刪除操作時,為了保證內存數據的連續性,往往需要做大量的數據搬移工作,所以時間復雜度是O(n)。
而在鏈表中插入或刪除數據時,因為鏈表結構中的節點並不需要連續的存儲空間,所以在鏈表中進行數據的插入和刪除時並不需要搬移節點。
對於鏈表的刪除和插入操作,我們只需要調整相鄰節點的后繼指針即可,所以對應的時間復雜度是O(1)。
雙向鏈表插入元素示例圖
插入元素算法(重點)
Link:當前正在遍歷的結點;lastLink:最后一個結點(全部遍歷完才知道誰是最后結點) Link<ET> link, lastLink;
public void add(ET object) { if (expectedModCount == list.modCount) { Link<ET> next = link.next; //現在link.next=a2; 所以next=a2
Link<ET> newlink = new Link<ET>(object, link, next); lick.next = newlink; //a1指向新的結點
next.previous = newLink; //a2的前驅指向了newLink,也就是2那條線
link = newLink;當前結點變成了newLink lastlink = null; pos++; expectedModCount++; list.size++; list.modCount++; } else { throw new ConcurrentModificationException();}
二分法查找
if(location<(size/2)){ for(int i = 0;i <= location;i++){ 1ink = link. next; } else{ for(int i = size;i > location;i--){ link = link. previous;
}
結點插入在前半段(從前往后):Next可以找到下一個結點 結點插入在后半段(從后往前):Previous可以找到前一個結點
remove
Link<E>previous=link.previous; 7
Link<E>next=link.next;
previous.next=next;
next.previous=previlus;
size--;
modCount++;
return link.data;