學習JAVA—數據結構之單鏈表與數組的區別、以及實現
http://blog.csdn.net/gg811/article/details/8466614 這是大牛地址
第一部分是首先說下數組與鏈表的區別~數組是大家常用的而熟知的,利用鏈表對比數組這樣可以加深對鏈表的記憶。第二部分就是鏈表的代碼實現,加深理解。
關於單鏈表:
1、概念
在單鏈表中由於數據元素的存儲空間一般不是連續的,因此為了完善的表示單鏈表的邏輯結構,其中每一個數據元素必須由兩部分構成:一部分是數據元素中的數據值,另一部分是數據元素的地址值。這兩部分信息構成了單鏈表的一個節點。因此,在用單鏈表表示線性表時,每個結點的存儲地址是任意的,即存儲位置是無序的。
2、結構
對於單鏈表來說,每個節點的結構都是(data,next),節點中有兩個部分:data域—存放結點值的數據域,next—存放結點的直接后續的地址的鏈域。
數組與鏈表的區別:
1、基於空間的考慮
數組的存儲空間是靜態,連續分布的,初始化的過大造成空間浪費,過小又將使空間溢出機會增多。而鏈表的存儲空間是動態分布的,只要內存空間尚有空閑,就不會產生溢出;鏈表中每個節點出了數據域外,還有鏈域(指向下一個節點),這樣空間利用率就會變高。
2、基於時間的考慮
具體的來說 數組查詢快,插入與刪除慢,單鏈表查詢慢,插入與刪除快。細說的話:數組中任意節點都可以在O(1)內直接存儲訪問,而鏈表中的節點,需從頭指針順着鏈表掃描才能獲取到;而鏈表任意位置進行插入和刪除,都只需要修改指針,而數組中插入刪除節點,平均要移動一半的節點。
(靜態)數組從棧中分配空間,對於程序員方便快速,但是自由度小。鏈表從堆中分配空間,自由度大但是申請管理比較麻煩。
數組中的數據在內存中按順序存儲的,而鏈表是隨機存儲的!
要訪問數組中的元素可以按下標索引來訪問,速度快,如果對他進行插入操作的話,就得移動很多元素,所以對數組進行插入操作效率很低!
由於鏈表是隨機存儲的,鏈表在插入,刪除操作上有很高的效率(相對於數組),如果要訪問鏈表中的某個元素的話,就得從鏈表的頭逐個遍歷,直到找到所需要的元素為止,所以鏈表的隨機訪問的效率就比數組要低。(這里會在下面代碼中顯示出來,在此做一個特殊的符號標記一下
,嗯就是這個把)。
單鏈表的實現代碼,走你~:
首先定義一個節點類~記錄每個節點使用:
- public class Node {
- String data;//數據域
- Node next;//鏈域
- public Node(String data) {
- this.data = data;
- next = null;
- }
- }
下列代碼就是構造了一個單鏈表,並且實現了各種操作:
- public class LinkedList {
- int lenght;// 鏈表的長度
- Node head;// 定義頭結點
- public LinkedList() {
- head = null;// 鏈表中的頭結點
- lenght = 0;
- }
- /** 在鏈表末尾添加一個元素 */
- public void addElement(Node n) {
- if (lenght == 0) {// 如果鏈表為空,則直接添加。
- head = n;
- } else {
- Node t = head;
- while (t.next != null) {// 沿鏈表第一個元素向后尋找,直到找到末尾
- t = t.next;
- }
- t.next = n;// 在末尾添加元素,也就是給最后一個next賦值~讓鏈域不為空,這樣鏈域為空的就成了鏈表中最后一個元素
- }
- // 在主函數中調用這個的方法為addElement(new Node("張三")),
- // 其中new一個Node 就確定了這個Node的數據域(data)為"張三",鏈域(next)為null,
- // 而這個函數的作用就是確定把這個新new出來Node放在誰的next中
- lenght++;// 修改長度
- }
- /** 在鏈表中特定位置添加一個元素 */
- public boolean insert(Node n, int index) {
- if (index > lenght && index < 0) {// 如果插入位置超出鏈表長度
- System.out.println("超出范圍!!");
- return false;
- } else {
- Node t = head;
- if (index == 0) {
- n.next = head;// 讓傳入的節點指向頭節點
- head = n;// n作為新的頭節點
- } else {
- for (int i = 0; i < index - 1; i++) {// 找到要插入的位置的前一個位置
- t = t.next;
- }
- n.next = t.next;// 新插入的節點指向當前位置節點
- t.next = n;
- // 這里需要用圖解釋的更為清晰
- // 可見本文下方圖—1;
- }
- lenght++;
- return true;
- }
- }
- /** 刪除鏈表最后一個節點 */
- public void removeLastElement() {
- if (lenght == 0) {
- System.out.println("鏈表中沒有元素");
- return;
- }
- Node t = head;
- if (lenght == 1) {
- head = null;
- } else {
- for (int i = 0; i < lenght - 1; i++) {// 找到末尾節點的前一個節點
- t = t.next;
- }
- t.next = null;
- }
- lenght--;
- }
- /** 刪除指定位置的節點 */
- public void removeElement(int index) {
- if (lenght == 0) {
- System.out.println("鏈表沒有元素!");
- return;
- }
- if (index > lenght && index < 0) {
- System.out.println("超出范圍!!");
- return;
- }
- Node t = head;
- if (index == 0) {
- head = head.next;
- t.next = null;
- lenght--;
- return;
- }
- for (int i = 0; i < index - 1; i++) {// 找到要刪除位置的前一位置
- t = t.next;
- }
- Node temp = t;
- t.next = t.next.next;
- temp.next = null;// 讓該節點的next指向空
- lenght--;
- }
- /** 清空鏈表 */
- public void clearList() {
- head = null;
- lenght = 0;
- }
- /** 打印鏈表中的所有元素 */
- public void printList() {
- if (lenght == 0) {
- System.out.println("鏈表為空!");
- return;
- }
- Node t = head;
- while (t!= null) {
- System.out.print(t.data + " ");
- t = t.next;
- }
- }
- }

圖—1
再接下來就是調用這個鏈表的各個操作了~順便瞎說說~在我沒學鏈表前~我看過嚴蔚敏老師的數據結構一書~其中的好多偽代碼我都曾嘗試用數組來解決,但是發現並沒有想象中那么容易實現~在學鏈表之后~再回顧數據結構這本書~其中大多數偽代碼都可以用鏈表來實現~我就覺得這個是我研究算法的一個好工具~嗯~廢話就這么多,以上這個栗子要是懶得動手打的話~我這還是會有一個打好的,同樣下載不要分數哦~~(http://download.csdn.net/detail/gg811/4963474)點擊打開鏈接
