數據結構之鏈表

在面試過程當中,數據結構和算法基本上算是研發類崗位必考的部分,而鏈表基本上又是數據結構中相對容易掌握、並且容易出題的部分,所以咱們先整理一下鏈表部分的經典題目。前端

(聲明:如下全部程序都是用java編寫)java

首先,咱們來定義一個鏈表的數據結構,以下:node

View Code

有了這個數據結構後,咱們須要一個方法來生成和輸出鏈表,其中鏈表中每一個元素的值採用的是隨機數。面試

生成鏈表的代碼以下:算法

View Code
 1     public static Link init(int count, int maxValue)  2  {  3 Link list = new Link();  4 Link temp = list;  5 Random r = new Random();  6  temp.set_Value(Integer.MIN_VALUE);  7 for (int i = 0; i < count; i++)  8  {  9 Link node = new Link(); 10  node.set_Value(r.nextInt(maxValue)); 11  temp.set_Next(node); 12 temp=node; 13  } 14 temp.set_Next(null); 15 return list; 16  } 17 18 public static Link init(int count) 19  { 20 return init(count, Integer.MAX_VALUE); 21 }

對於鏈表的頭結點,咱們是不存儲任何信息的,所以將其值設置爲Integer.MIN_VALUE。咱們重載了生成鏈表的方法。數據庫

下面是打印鏈表信息的方法:編程

View Code
 1     public static void printList(Link list)  2  {  3 if (list == null || list.get_Next() == null)  4  {  5 System.out.println("The list is null or empty.");  6 return;  7  }  8 Link temp = list.get_Next();  9 StringBuffer sb = new StringBuffer(); 10 while(temp != null) 11  { 12 sb.append(temp.get_Value() + "->"); 13 temp=temp.get_Next(); 14  } 15 System.out.println(sb.substring(0, sb.length() - 2)); 16 }

好了,有了以上這些基礎的方法, 咱們就能夠深刻探討鏈表相關的面試題了。後端

  • 鏈表反轉 思路:有兩種方法能夠實現鏈表反轉,第一種是直接循環每一個元素,修改它的Next屬性;另外一種是採起遞歸的方式。 首先來看直接循環的方式:
    View Code
     1     public static Link Reverve(Link list)  2  {  3 if (list == null || list.get_Next() == null || list.get_Next().get_Next() == null)  4  {  5 System.out.println("list is null or just contains 1 element, so do not need to reverve.");  6 return list;  7  }  8 Link current = list.get_Next();  9 Link next = current.get_Next(); 10 current.set_Next(null); 11 while(next != null) 12  { 13 Link temp = next.get_Next(); 14  next.set_Next(current); 15 current = next; 16 next = temp; 17  } 18  list.set_Next(current); 19 20 return list; 21 }

    而後是遞歸方式:數組

    View Code
     1     public static Link RecursiveReverse(Link list)  2  {  3 if (list == null || list.get_Next() == null || list.get_Next().get_Next() == null)  4  {  5 System.out.println("list is null or just contains 1 element, so do not need to reverve.");  6 return list;  7  }  8  9  list.set_Next(Recursive(list.get_Next())); 10 11 return list; 12  } 13 14 15 private static Link Recursive(Link list) 16  { 17 if (list.get_Next() == null) 18  { 19 return list; 20  } 21 Link temp = Recursive(list.get_Next()); 22  list.get_Next().set_Next(list); 23 list.set_Next(null); 24 25 return temp; 26 
  • 輸出指定位置的元素(倒數第N個元素) 思路:採用兩個遊標來遍歷鏈表,第1個遊標先走N步,而後兩個遊標同時前進,當第一個遊標到最後時,第二個遊標就是想要的元素。
    View Code
     1     public static Link find(Link list, int rPos)  2  {  3 if (list == null || list.get_Next() == null)  4  {  5 return null;  6  }  7 int i = 1;  8 Link first = list.get_Next();  9 Link second = list.get_Next(); 10 while(true) 11  { 12 if (i==rPos || first == null) break; 13 first = first.get_Next(); 14 i++; 15  } 16 if (first == null) 17  { 18 System.out.println("The length of list is less than " + rPos + "."); 19 return null; 20  } 21 while(first.get_Next() != null) 22  { 23 first = first.get_Next(); 24 second = second.get_Next(); 25  } 26 27 return second; 28 }
  • 刪除指定節點 思路:能夠分狀況討論,若是指定節點不是尾節點,那麼能夠採用取巧的方式,將指定節點的值修改成下一個節點的值,將指定節點的Next屬性設置爲Next.Next;但若是指定節點爲尾節點,那麼只能是從頭開始遍歷。
    View Code
     1     public static void delete(Link list, Link element)  2  {  3 if (element.get_Next() != null)  4  {  5  element.set_Value(element.get_Next().get_Value());  6  element.set_Next(element.get_Next().get_Next());  7  }  8 else  9  { 10 Link current = list.get_Next(); 11 while(current.get_Next() != element) 12  { 13 current = current.get_Next(); 14  } 15 current.set_Next(null); 16  } 17 }
  • 刪除重複節點 思路:採用hashtable來存取鏈表中的元素,遍歷鏈表,當指定節點的元素在hashtable中已經存在,那麼刪除該節點。
    View Code
     1     public static void removeDuplicate(Link list)  2  {  3 if (list == null || list.get_Next() == null || list.get_Next().get_Next() == null) return;  4 Hashtable table = new Hashtable();  5 Link cur = list.get_Next();  6 Link next = cur.get_Next();  7 table.put(cur.get_Value(), 1);  8 while(next != null)  9  { 10 if (table.containsKey(next.get_Value())) 11  { 12  cur.set_Next(next.get_Next()); 13 next = next.get_Next(); 14  } 15 else 16  { 17 table.put(next.get_Value(), 1); 18 cur= next; 19 next = next.get_Next(); 20  } 21 22  } 23 }
  • 尋找鏈表中間節點 思路:採用兩個遊標的方式,第一個遊標每次前進兩步,第二個遊標每次前進一步,當第一個遊標到最後時,第二個遊標就是中間位置。須要注意的是,若是鏈表元素的個數是偶數,那麼中間元素應該是兩個。
    View Code
     1     public static void findMiddleElement(Link list)  2  {  3 if (list == null || list.get_Next() == null) return;  4 System.out.println("The Middle element is:");  5 if (list.get_Next().get_Next() == null)  6  {  7  System.out.println(list.get_Next().get_Value());  8  }  9 Link fast = list.get_Next(); 10 Link slow = list.get_Next(); 11 while(fast.get_Next() != null && fast.get_Next().get_Next() != null) 12  { 13 fast = fast.get_Next().get_Next(); 14 slow = slow.get_Next(); 15  } 16 17 if (fast != null && fast.get_Next() == null) 18  { 19  System.out.println(slow.get_Value()); 20  } 21 else 22  { 23  System.out.println(slow.get_Value()); 24  System.out.println(slow.get_Next().get_Value()); 25  } 26 }
  • 鏈表元素排序 思路:鏈表元素排序,有兩種方式,一種是鏈表元素自己的排序,一種是鏈表元素值得排序。第二種方式更簡單、靈活一些。
    View Code
     1     public static void Sort(Link list)  2  {  3 if (list == null || list.get_Next() == null || list.get_Next().get_Next() == null)  4  {  5 return;  6  }  7 Link current = list.get_Next();  8 Link next = current.get_Next();  9 while(current.get_Next() != null) 10  { 11 while(next != null) 12  { 13 if (current.get_Value() > next.get_Value()) 14  { 15 int temp = current.get_Value(); 16  current.set_Value(next.get_Value()); 17  next.set_Value(temp); 18  } 19 next = next.get_Next(); 20  } 21 current = current.get_Next(); 22 next = current.get_Next(); 23  } 24 }
  • 判斷鏈表是否有環,若是有,找出環上的第一個節點 思路:能夠採用兩個遊標的方式判斷鏈表是否有環,一個遊標跑得快,一個遊標跑得慢。當跑得快的遊標追上跑得慢的遊標時,說明有環;當跑得快的遊標跑到尾節點時,說明無環。 至於如何找出換上第一個節點,能夠分兩步,首先肯定環上的某個節點,計算頭結點到該節點的距離以及該節點在環上循環一次的距離,而後創建兩個遊標,分別指向頭結點和環上的節點,並將距離平攤(哪一個距離大,先移動哪一個遊標,直至兩個距離相等),最後同時移動兩個遊標,碰到的第一個相同元素,就是環中的第一個節點。
    View Code
     1     public static Link getLoopStartNode(Link list)  2  {  3 if (list == null || list.get_Next() == null || list.get_Next().get_Next() == null)  4  {  5 return null;  6  }  7 int m = 1, n = 1;  8 Link fast = list.get_Next();  9 Link slow = list.get_Next(); 10 while(fast != null && fast.get_Next() != null) 11  { 12 fast = fast.get_Next().get_Next(); 13 slow = slow.get_Next(); 14 if (fast == slow) break; 15 m++; 16  } 17 if (fast != slow) 18  { 19 return null; 20  } 21 Link temp = fast; 22 while(temp.get_Next() != fast) 23  { 24 temp = temp.get_Next(); 25 n++; 26  } 27 Link node1 = list.get_Next(); 28 Link node2 = fast; 29 if (m < n) 30  { 31 for (int i = 0; i < n - m; i++) 32  { 33 node2 = node2.get_Next(); 34  } 35  } 36 if (m > n) 37  { 38 for (int i = 0; i < m - n; i++) 39  { 40 node1 = node1.get_Next(); 41  } 42  } 43 while(true) 44  { 45 if (node1 == node2) 46  { 47 break; 48  } 49 node1 = node1.get_Next(); 50 node2 = node2.get_Next(); 51  } 52 53 return node1; 54 55 }
  • 判斷兩個鏈表是否相交 思路:判斷兩個鏈表的尾節點是否相同,若是相同,必定相交
    View Code
     1     public static boolean isJoint(Link list1, Link list2)  2  {  3 if (list1 == null || list2 == null || list1.get_Next() == null || list2.get_Next() == null)  4  {  5 return false;  6  }  7 Link node1 = list1;  8 Link node2 = list2;  9 while(node1.get_Next() != null) 10  { 11 node1 = node1.get_Next(); 12  } 13 while(node2.get_Next() != null) 14  { 15 node2 = node2.get_Next(); 16  } 17 18 return node1 == node2; 19 }
  • 合併兩個有序鏈表 思路:新建一個鏈表,而後同時遍歷兩個有序鏈表,比較其大小,將元素較小的鏈表向前移動,直至某一個鏈表元素爲空。而後將非空鏈表上的全部元素追加到新建鏈表中。
    View Code
     1     public static Link merge(Link list1, Link list2)  2  {  3 Link list = new Link();  4  list.set_Value(Integer.MIN_VALUE);  5 Link current1 = list1.get_Next();  6 Link current2 = list2.get_Next();  7 Link current = list;  8 while(current1 != null && current2 != null)  9  { 10 Link temp = new Link(); 11 if (current1.get_Value() > current2.get_Value()) 12  { 13  temp.set_Value(current2.get_Value()); 14 current2 = current2.get_Next(); 15  } 16 else 17  { 18  temp.set_Value(current1.get_Value()); 19 current1 = current1.get_Next(); 20  } 21  current.set_Next(temp); 22 current = temp; 23  } 24 if (current1 != null) 25  { 26 while(current1 != null) 27  { 28 Link temp = new Link(); 29  temp.set_Value(current1.get_Value()); 30  current.set_Next(temp); 31 current = temp; 32 current1 = current1.get_Next(); 33  } 34  } 35 36 if (current2 != null) 37  { 38 while(current2 != null) 39  { 40 Link temp = new Link(); 41  temp.set_Value(current2.get_Value()); 42  current.set_Next(temp); 43 current = temp; 44 current2 = current2.get_Next(); 45  } 46  } 47 48 current.set_Next(null); 49 50 return list; 51 }
  • 交換鏈表中任意兩個元素(非頭結點) 思路:首先須要保存兩個元素的pre節點和next節點,而後分別對pre節點和next節點的Next屬性從新賦值。須要注意的是,當兩個元素師相鄰元素時,須要特殊處理,不然會將鏈表陷入死循環。
    View Code
     1     public static void swap(Link list, Link element1, Link element2)  2  {  3 if (list == null || list.get_Next() == null || list.get_Next().get_Next() == null ||  4 element1 == null || element2 == null || element1 == element2)  5 return;  6  7 Link pre1 = null, pre2 = null, next1 = null, next2 = null;  8 Link cur1=element1, cur2=element2;  9 Link temp = list.get_Next(); 10 boolean bFound1 = false; 11 boolean bFound2 = false; 12 while(temp != null) 13  { 14 if(temp.get_Next() == cur1) 15  { 16 pre1=temp; 17 next1 = temp.get_Next().get_Next(); 18 bFound1 = true; 19  } 20 if (temp.get_Next() == cur2) 21  { 22 pre2 = temp; 23 next2 = temp.get_Next().get_Next(); 24 bFound2=true; 25  } 26 if (bFound1 && bFound2) break; 27 temp = temp.get_Next(); 28  } 29 30 if (cur1.get_Next() == cur2) 31  { 32 temp = cur2.get_Next(); 33  pre1.set_Next(cur2); 34  cur2.set_Next(cur1); 35  cur1.set_Next(temp); 36  } 37 else if (cur2.get_Next() == cur1) 38  { 39 temp = cur1.get_Next(); 40  pre2.set_Next(cur1); 41  cur1.set_Next(cur2); 42  cur2.set_Next(temp); 43  } 44 else 45  { 46  pre1.set_Next(cur2); 47  cur1.set_Next(next2); 48  pre2.set_Next(cur1); 49  cur2.set_Next(next1); 50  } 51 }

    這裏,還有另一種取巧的方法,就是直接交換兩個元素的值,而不須要修改引用。數據結構

    View Code
     1     public static void swapValue(Link list, Link element1, Link element2)  2  {  3 if (element1 == null || element2 == null)  4  {  5 return;  6  }  7 int temp = element1.get_Value();  8  element1.set_Value(element2.get_Value());  9  element2.set_Value(temp); 10 }

    不過,這種方式,應該不是面試官所但願看到的。

 

定義

數據結構名詞定義

  • 數據結構是指 相互之間存在着一種或多種關係的 數據 元素的集合和該集合中數據 元素 之間的關係組成。記爲:
Data_Structure=(D,R)
其中D是數據元素的 集合 R是該集合中全部元素之間的關係的 有限集合

數據結構其它定義

Sartaj Sahni在他的《數據結構、算法與應用》一書中稱:「數據結構是 數據對象,以及存在於該對象的 實例和組成實 例的 數據元素之間的各類聯繫。這些聯繫能夠經過定義相關的 函數來給出。」他將 數據對象(data object)定義爲「一個數據對象是 實例的集合」。
Clifford A.Shaffer在《 數據結構與算法分析》一書中的 定義是:「數據結構是 ADT抽象數據類型Abstract Data Type) 的物理實現。」
Robert L.Kruse在《數據結構與程序設計》一書中,將一個數據結構的設計過程分紅抽象層、數據結構層和實現層。其中,抽象層是指抽象數據類型層,它討論數據的 邏輯結構及其 運算,數據結構層和實現層討論一個數據結構的表示和在計算機內的存儲細節以及運算的實現。
數據結構具體指同一類數據元素中,各元素之間的相互 關係,包括三個組成 成分,數據的 邏輯結構數據的存儲結構和數據運算結構。

數據結構研究對象

1、數據的邏輯結構:指反映數據 元素之間的邏輯關係的 數據結構,其中的邏輯關係是指數據元素之間的先後件關係,而與他們在計算機中的存儲位置無關。邏輯結構包括:
  1. 集合
數據結構中的元素之間除了「同屬一個集合」 的相互關係外,別無其餘關係;
數據結構中的元素存在一對一的相互關係;
數據結構中的元素存在一對多的相互關係;
數據結構中的元素存在多對多的相互關係。
2、數據的物理結構:指數據的 邏輯結構在計算機存儲空間的存放形式。
數據的物理結構是數據結構在計算機中的表示(又稱映像),它包括數據元素的機內表示和關係的機內表示。因爲具體實現的方法有順序、連接、索引、散列等多種,因此,一種數據結構可表示成一種或多種存儲結構。
數據元素的機內表示(映像方法): 用二進制位(bit)的位串表示數據元素。一般稱這種位串爲節點(node)。當數據元素有若干個數據項組成時,位串中與個數據項對應的子位串稱爲數據域(data field)。所以,節點是數據元素的機內表示(或機內映像)。
關係的機內表示(映像方法):數據元素之間的關係的機內表示能夠分爲順序映像和非順序映像,經常使用兩種存儲結構:順序存儲結構和鏈式存儲結構。順序映像藉助元素在存儲器中的相對位置來表示數據元素之間的邏輯關係。非順序映像藉助指示元素存儲位置的指針(pointer)來表示數據元素之間的邏輯關係。
3、數據結構的運算

數據結構重要意義

通常認爲,一個數據結構是由數據元素依據某種邏輯聯繫組織起來的。對數據元素間邏輯關係的描述稱爲數據的邏輯結構;數據必須在計算機內存儲,數據的 存儲結構是數據結構的實現形式,是其在計算機內的表示;此外討論一個數據結構必須同時討論在該類數據上執行的運算纔有意義。一個邏輯數據結構能夠有多種 存儲結構,且各類 存儲結構影響數據處理的效率。
在許多類型的 程序的設計中,數據結構的選擇是一個基本的設計考慮因素。許多大型系統的構造經驗代表,系統實現的困難程度和系統構造的質量都嚴重的依賴因而否選擇了最優的數據結構。許多時候,肯定了數據結構後,算法就容易獲得了。有些時候事情也會反過來,咱們根據特定算法來選擇數據結構與之適應。不論哪一種狀況,選擇合適的數據結構都是很是重要的。
選擇了數據結構,算法也隨之肯定,是數據而不是算法是系統構造的關鍵因素。這種洞見致使了許多種 軟件設計方法和 程序設計語言的出現, 面向對象的程序設計語言就是其中之一。

數據結構研究內容

在計算機科學中,數據結構是一門研究非數值計算的程序設計問題中計算機的操做對象(數據元素)以及它們之間的關係和運算等的學科,並且確保通過這些運算後所獲得的新結構仍然是原來的結構類型。
「數據結構」做爲一門獨立的課程在國外是從1968年纔開始設立的。 1968年美國唐納德·克努特(Donald Ervin Knuth)教授開創了數據結構的最初體系,他所著的《計算機程序設計藝術》第一卷《基本算法》是第一本較系統地闡述數據的邏輯結構和存儲結構及其操做的著做。「數據結構」在計算機科學中是一門綜合性的專業基礎課,數據結構是介於數學、計算機硬件和計算機軟件三者之間的一門核心課程。數據結構這一門課的內容不只是通常程序設計(特別是非數值性程序設計)的基礎,並且是設計和實現編譯程序、操做系統、數據庫系統及其餘系統程序的重要基礎。
計算機科學是一門研究用計算機進行信息表示和處理的科學。這裏面涉及到兩個問題:信息的表示,信息的處理 。
而信息的表示和組織又直接關係處處理信息的程序的效率。隨着計算機的普及,信息量的增長,信息範圍的拓寬,使許多系統程序和 應用程序的規模很大,結構又至關複雜。所以,爲了編寫出一個「好」的程序,必須分析待處理的 對象的特徵及各對象之間存在的關係,這就是數據結構這門課所要研究的問題。衆所周知,計算機的程序是對信息進行加工處理。在大多數狀況下,這些信息並非沒有組織,信息(數據)之間每每具備重要的結構關係,這就是數據結構的內容。數據的結構,直接影響算法的選擇和效率。
計算機解決一個具體問題時,大體須要通過下列幾個步驟:首先要從具體問題中抽象出一個適當的 數學模型,而後設計一個解此數學模型的 算法(Algorithm),最後編出程序、進行測試、調整直至獲得最終解答。
尋求數學模型的實質是分析問題,從中提取操做的對象,並找出這些操做對象之間含有的關係,而後用數學的語言加以描述。當人們用計算機處理數值計算問題是,所用的數學模型是用數學方程描述。所涉及的運算對象通常是簡單的整形、實型和邏輯型數據,所以程序設計者的主要精力集中於程序設計技巧上,而不是數據的存儲和組織上。然而,計算機應用的更多領域是「非數值型計算問題」,它們的數學模型沒法用數學方程描述,而是用數據結構描述,解決此類問題的關鍵是設計出合適的數據結構,描述非數值型問題的數學模型是用線性表、樹、圖等結構來描述的。
計算機算法與數據的結構密切相關,算法無不依附於具體的數據結構,數據結構直接關係到算法的選擇和效率。運算是由計算機來完成,這就要設計相應的插入、刪除和修改的算法 。也就是說,數據結構還須要給出每種結構類型所定義的各類運算的算法。
數據是信息的載體,是能夠被計算機識別存儲並加工處理的描述客觀事物的信息符號的總稱。全部能被輸入計算機中,且能被計算機處理的符號的集合,它是計算機程序加工處理的對象。客觀事物包括數值、字符、聲音、圖形、圖像等,它們自己並非數據,只有經過編碼變成能被計算機識別、存儲和處理的符號形式後纔是數據。
數據元素是數據的 基本單位,在計算機程序中一般做爲一個總體考慮。一個數據元素由若干個 數據項組成。數據項是數據結構中討論的最小單位。有兩類數據元素:若數據元素可再分,則每個獨立的處理單元就是數據項,數據元素是數據項的集合;若數據元素不可再分,則數據元素和數據項是同一律念,如:整數"5",字符 "N" 等。例如描述一個學生的信息的數據元素可由下列6個數據項組成。其中的出生日期又能夠由三個數據項:"年"、"月"和"日"組成,則稱"出生日期"爲組合項,而其它不可分割的數據項爲原子項。
關鍵字指的是能識別一個或多個數據元素的數據項。若能起惟一識別做用,則稱之爲 "主" 關鍵字,不然稱之爲 "次" 關鍵字。
數據對象是性質相同的數據元素的集合,是數據的一個 子集。數據對象能夠是有限的,也能夠是無限的。
數據處理是指對數據進行 查找插入、刪除、合併、 排序、統計以及簡單計算等的操做過程。在早期,計算機主要用於科學和 工程計算,進入八十年代之後,計算機主要用於數據處理。據有關統計資料代表,計算機用於數據處理的時間比例達到80%以上,隨着時間的推移和 計算機應用的進一步普及,計算機用於數據處理的時間比例必將進一步增大。

數據結構結構分類

數據結構是指同一數據元素類中各數據元素之間存在的關係。數據結構分別爲 邏輯結構存儲結構物理結構)和數據的運算。數據的邏輯結構是從具體問題抽象出來的數學模型,是描述數據元素及其關係的數學特性的,有時就把邏輯結構簡稱爲數據結構。邏輯結構是在計算機存儲中的映像,形式地定義爲(K,R)(或(D,S)),其中,K是數據元素的有限集,R是K上的關係的有限集。
根據數據元素間關係的不一樣特性,一般有下列四類基本的結構:
⑴集合結構。該結構的數據元素間的關係是「屬於同一個集合」。
⑵線性結構。該結構的數據元素之間存在着一對一的關係。
⑶樹型結構。該結構的數據元素之間存在着一對多的關係。
⑷圖形結構。該結構的數據元素之間存在着多對多的關係,也稱網狀結構。 從上面所介紹的數據結構的概念中能夠知道,一個數據結構有兩個要素。一個是數據元素的集合,另外一個是關係的集合。在形式上,數據結構一般能夠採用一個二元組來表示。
數據結構的形式定義爲:數據結構是一個二元組 :Data_Structure=(D,R),其中,D是數據元素的有限集,R是D上關係的有限集。 線性結構的特色是數據元素之間是一種線性關係,數據元素「一個接一個的排列」。在一個 線性表數據元素的類型是相同的,或者說線性表是由同一類型的數據元素構成的線性結構。在實際問題中線性表的例子是不少的,如學生狀況信息表是一個線性表:表中數據元素的類型爲學生類型; 一個字符串也是一個線性表:表中數據元素的類型爲字符型,等等。
線性表是最簡單、最基本、也是最經常使用的一種線性結構。 線性表是具備相同數據類型的n(n>=0)個數據元素的有限序列,一般記爲: (a1,a2,… ai-1,ai,ai+1,…an) ,其中n爲表長, n=0 時稱爲空表。 它有兩種存儲方法:順序存儲和鏈式存儲,它的主要基本操做是插入、刪除和檢索等。
數據結構在計算機中的表示(映像)稱爲數據的物理(存儲)結構。它包括數據元素的表示和關係的表示。數據元素之間的關係有兩種不一樣的表示方法:順序映象和非順序映象,並由此獲得兩種不一樣的存儲結構:順序存儲結構和 鏈式存儲結構
順序存儲方法:它是把邏輯上相鄰的結點存儲在物理位置相鄰的 存儲單元裏,結點間的邏輯關係由存儲單元的鄰接關係來體現,由此獲得的存儲表示稱爲順序存儲結構。順序存儲結構是一種最基本的存儲表示方法,一般藉助於程序設計語言中的數組來實現。
連接存儲方法:它不要求邏輯上相鄰的結點在物理位置上亦相鄰,結點間的邏輯關係是由附加的 指針字段表示的。由此獲得的存儲表示稱爲鏈式存儲結構,鏈式存儲結構一般藉助於程序設計語言中的指針類型來實現
索引存儲方法:除創建存儲結點信息外,還創建附加的索引表來標識結點的 地址
散列存儲方法:就是根據結點的關鍵字直接計算出該結點的存儲地址。
數據結構中,邏輯上(邏輯結構:數據元素之間的邏輯關係)能夠把數據結構分紅線性結構和非線性結構。線性結構的順序存儲結構是一種順序存取的存儲結構, 線性表的鏈式存儲結構是一種 隨機存取的存儲結構。線性表若採用鏈式存儲表示時全部結點之間的存儲單元地址可連續可不連續。邏輯結構與數據元素自己的形式、內容、相對位置、所含結點個數都無關。

數據結構結構算法

算法的設計取決於數據(邏輯)結構,而算法的實現依賴於採用的存儲結構。數據的存儲結構實質上是它的邏輯結構在計算機 存儲器中的實現,爲了全面的反映一個數據的邏輯結構,它在 存儲器中的映象包括兩方面內容,即數據元素之間的信息和數據元素之間的關係。不一樣數據結構有其相應的若干運算。數據的運算是在數據的邏輯結構上定義的操做算法,如檢索、插入、刪除、更新和排序等。
數據的運算是數據結構的一個重要方面,討論任一種數據結構時都離不開對該結構上的 數據運算及其實現算法的討論。
數據結構不一樣於 數據類型,也不一樣於數據對象,它不只要描述數據類型的數據對象,並且要描述數據對象各元素之間的相互關係。
數據類型是一個值的集合和定義在這個值集上的一組操做的總稱。數據類型可分爲兩類:原子類型、結構類型。一方面,在程序設計語言中,每個數據都屬於某種數據類型。類型明顯或隱含地規定了數據的取值範圍、存儲方式以及容許進行的運算。能夠認爲,數據類型是在程序設計中已經實現了的數據結構。另外一方面,在程序設計過程當中,當須要引入某種新的數據結構時,老是藉助 編程語言所提供的數據類型來描述數據的存儲結構。
計算機中表示數據的最小單位是二進制數的一位,叫作位。咱們用一個由若干位組合起來造成的一個位串表示一個數據元素,一般稱這個位串爲元素或結點。當數據元素由若干數據項組成時,位串中對應於各個數據項的子位串稱爲數據域。元素或結點可當作是數據元素在計算機中的映象。
一個 軟件系統框架應創建在數據之上,而不是創建在操做之上。一個含抽象數據類型的軟件模塊應包含定義、表示、實現三個部分。
對每個數據結構而言,一定存在與它密切相關的一組操做。若操做的種類和數目不一樣,即便邏輯結構相同,數據結構能起的做用也不一樣。
不一樣的數據結構其操做集不一樣,但下列操做必不可缺:
1,結構的生成;
2.結構的銷燬;
3,在結構中查找知足規定條件的數據元素;
4,在結構中插入新的數據元素;
5,刪除結構中已經存在的數據元素;
6,遍歷。
抽象數據類型:一個數學模型以及定義在該模型上的一組操做。抽象數據類型實際上就是對該數據結構的定義。由於它定義了一個數據的邏輯結構以及在此結構上的一組算法。抽象數據類型可用如下 三元組表示:(D,S,P)。D是數據對象,S是D上的關係集,P是對D的基本操做集。 ADT的定義爲:
ADT 抽象數據類型名:{數據對象:(數據元素集合),數據關係:(數據關係二元組結合),基本操做:(操做函數的羅列)}; ADT抽象數據類型名;抽象數據類型有兩個重要特性:
用ADT描述程序處理的 實體時,強調的是其本質的特徵、其所能完成的功能以及它和外部用戶的 接口(即外界使用它的方法)。
將實體的外部特性和其內部實現細節分離,而且對外部用戶隱藏其內部實現細節。
數據(Data)是信息的載體,它可以被計算機識別、存儲和加工處理。它是計算機程序加工的原料,應用程序處理各類各樣的數據。計算機科學中,所謂數據就是計算機加工處理的對象,它能夠是 數值數據,也能夠是非數值數據。數值數據是一些整數、實數或複數,主要用於 工程計算、科學計算和商務處理等;非數值數據包括字符、文字、 圖形、圖像、語音等。數據元素(Data Element)是數據的基本單位。在不一樣的條件下,數據元素又可稱爲元素、結點、頂點、記錄等。例如,學生 信息檢索系統中學生信息表中的一個記錄等,都被稱爲一個數據元素。
有時,一個數據元素可由若干個數據項(Data Item)組成,例如, 學籍管理系統中學生信息表的每個數據元素就是一個學生記錄。它包括學生的學號、 姓名、性別、籍貫、出生年月、成績等數據項。這些數據項能夠分爲兩種:一種叫作初等項,如學生的性別、籍貫等,這些數據項是在數據處理時不能再分割的最小單位;另外一種叫作組合項,如學生的成績,它能夠再劃分爲數學、物理、化學等更小的項。一般,在解決實際應用問題時是把每一個學生記錄看成一個基本單位進行訪問和處理的。
數據對象(Data Object)或數據元素類(Data Element Class)是具備相同性質的數據元素的集合。在某個具體問題中,數據元素都具備相同的性質(元素值不必定相等),屬於同一數據對象(數據元素類),數據元素是數據元素類的一個實例。例如,在交通諮詢系統的交通網中,全部的頂點是一個數據元素類,頂點A和頂點B各自表明一個城市,是該數據元素類中的兩個實例,其數據元素的值分別爲A和B。 數據結構(Data Structure)是指互相之間存在着一種或多種關係的數據元素的集合。在任何問題中,數據元素之間都不會是孤立的,在它們之間都存在着這樣或那樣的關係,這種數據元素之間的關係稱爲結構。

數據結構經常使用結構

數據結構數組

在程序設計中,爲了處理方便, 把具備相同類型的若干 變量按有序的形式組織起來。這些按序排列的同類數據元素的集合稱爲 數組。在 C語言中, 數組屬於構造數據類型。一個數組能夠分解爲多個數組元素,這些數組元素能夠是基本數據類型或是構造類型。所以按數組元素的類型不一樣,數組又可分爲數值數組、字符數組、 指針數組、結構數組等各類類別。

數據結構棧

是隻能在某一端插入和刪除的特殊 線性表。它按照先進後出的原則存儲數據,先進入的數據被壓入棧底,最後的數據在棧頂,須要讀數據的時候從棧頂開始彈出數據(最後一個數據被第一個讀出來)。

數據結構隊列

一種特殊的 線性表,它只容許在表的 前端(front)進行刪除操做,而在表的後端(rear)進行插入操做。進行插入操做的端稱爲隊尾,進行刪除操做的端稱爲隊頭。隊列是按照「先進先出」或「後進後出」的原則組織數據的。隊列中沒有元素時,稱爲空隊列。

數據結構鏈表

是一種物理存儲單元上非連續、非順序的存儲結構,它既能夠表示線性結構,也能夠用於表示非線性結構,數據元素的 邏輯順序是經過鏈表中的指針連接次序實現的。鏈表由一系列結點(鏈表中每個元素稱爲結點)組成,結點能夠在運行時 動態生成。每一個結點包括兩個部分:一個是存儲數據元素的數據域,另外一個是存儲下一個結點地址的指針域。

數據結構樹

是包含n(n>0)個結點的有窮集合K,且在K中定義了一個關係N,N知足 如下條件:
(1)有且僅有一個結點 K0,他對於關係N來講沒有前驅,稱K0爲樹的根結點。簡稱爲根( root)。 
(2)除K0外,K中的每一個結點,對於關係N來講有且僅有一個前驅。
(3)K中各結點,對關係N來講能夠有m個後繼(m>=0)。

數據結構圖

圖是由結點的有窮集合V和邊的集合E組成。其中,爲了與樹形結構加以 區別,在圖結構中經常將結點稱爲頂點,邊是頂點的有序偶對,若兩個頂點之間存在一條邊,就表示這兩個頂點具備相鄰關係。

數據結構堆

在計算機科學中,堆是一種特殊的樹形數據結構,每一個結點都有一個值。一般咱們所說的堆的數據結構,是指二叉堆。堆的特色是根結點的值最小(或最大),且根結點的兩個子樹也是一個堆。

數據結構散列表

若結構中存在關鍵字和K相等的記錄,則一定在f(K)的存儲位置上。由此,不需比較即可直接取得所查記錄。稱這個對應關係f爲散列函數(Hash function),按這個思想創建的表爲 散列表
相關文章
相關標籤/搜索