這兩天看到不少有關單鏈表的面試題,對單鏈表都不知道是啥的我。通過學習和整理來分享一下啥是單鏈表和單鏈表的一些基本使用方法。最後看些網上有關單鏈表的面試題代碼實例。面試
單鏈表是一種鏈式存取的數據結構,用一組地址任意的存儲單元存放線性表中的數據元素。這組存儲單元既能夠是連續的,也能夠是不連續的。數據結構
鏈表中的數據是以結點來表示的,每一個結點的構成:元素(數據元素的映象) + 指針(指示後繼元素存儲位置),元素就是存儲數據的存儲單元,指針就是鏈接每一個結點的地址數據。ide
鏈表的結點結構:學習
public class Node<T> { public T Data { set; get; } //數據域,當前結點數據 public Node<T> Next { set; get; } //位置域,下一個結點地址 public Node(T item) { this.Data = item; this.Next = null; } public Node() { this.Data = default(T); this.Next = null; } }
public class LinkList<T> { public Node<T> Head { set; get; } //單鏈表頭 //構造 public LinkList() { Head=null; } /// <summary> /// 增長新元素到單鏈表末尾 /// </summary> public void Append(T item) { Node<T> foot = new Node<T>(item); Node<T> A = new Node<T>(); if (Head == null) { Head = foot; return; } A = Head; while (A.Next != null) { A = A.Next; } A.Next = foot; } }
1.若是增長的是頭結點。直接把數據域(Data)給Head,Next爲空。由於只有一個頭結點,沒有對應的下結點。this
2.單鏈表是」不走回頭路「,因此每次增長都要從單鏈表的頭開始找到單鏈表最後一個結點(最後一個結點就是Next爲NULL),而後把最後一個結點的Next設置成需增長的結點,這時要需增長的結點變身爲最後一結點,他的Next爲NULL。spa
public class LinkList<T> { public Node<T> Head { set; get; } //單鏈表頭 //構造 public LinkList() { Head=null; }
public void Delete(int i) { Node<T> A = new Node<T>(); if (i == 1) //刪除頭 { A = Head; Head = Head.Next; return; } Node<T> B = new Node<T>(); B = Head; int j = 1; while (B.Next != null && j < i) { A = B; B = B.Next; j++; } if (j == i) { A.Next = B.Next; } } }
1.若是刪除的是頭結點,那如今的頭結點就應該是頭結點的下一結點。3d
2.刪除結點若是不是頭結點。從單鏈表頭開始查詢要刪除結點的位置。並記錄刪除的前一結點值A和所要刪除的結點B。由於結點B被刪除了,因此結點A的Next就應該爲B的Next。把結點A的Next設置爲結點B的Next。指針
public class LinkList<T> { public Node<T> Head { set; get; } //單鏈表頭 //構造 public LinkList() { Clear(); } /// <summary> /// 求單鏈表的長度 /// </summary> /// <returns></returns> public int GetLength() { Node<T> p = Head; int length = 0; while (p != null) { p = p.Next; length++; } return length; } /// <summary> /// 判斷單鍵表是否爲空 /// </summary> /// <returns></returns> public bool IsEmpty() { if (Head == null) return true; else return false; } /// <summary> /// 清空單鏈表 /// </summary> public void Clear() { Head = null; } /// <summary> /// 得到當前位置單鏈表中結點的值 /// </summary> /// <param name="i">結點位置</param> /// <returns></returns> public T GetNodeValue(int i) { if (IsEmpty() || i<1 || i>GetLength()) { Console.WriteLine("單鏈表爲空或結點位置有誤!"); return default(T); } Node<T> A = new Node<T>(); A = Head; int j = 1; while (A.Next!=null && j<i) { A = A.Next; j++; } return A.Data; } /// <summary> /// 增長新元素到單鏈表末尾 /// </summary> public void Append(T item) { Node<T> foot = new Node<T>(item); Node<T> A = new Node<T>(); if (Head == null) { Head = foot; return; } A = Head; while (A.Next != null) { A = A.Next; } A.Next = foot; } /// <summary> /// 增長單鏈表插入的位置 /// </summary> /// <param name="item">結點內容</param> /// <param name="n">結點插入的位置</param> public void Insert(T item, int n) { if (IsEmpty() || n < 1 || n > GetLength()) { Console.WriteLine("單鏈表爲空或結點位置有誤!"); return; } if (n == 1) //增長到頭部 { Node<T> H = new Node<T>(item); H.Next = Head; Head = H; return; } Node<T> A = new Node<T>(); Node<T> B = new Node<T>(); B = Head; int j = 1; while (B.Next != null && j < n) { A = B; B = B.Next; j++; } if (j==n) { Node<T> C = new Node<T>(item); A.Next = C; C.Next = B; } } /// <summary> /// 刪除單鏈表結點 /// </summary> /// <param name="i">刪除結點位置</param> /// <returns></returns> public void Delete(int i) { if (IsEmpty() || i < 1 || i > GetLength()) { Console.WriteLine("單鏈表爲空或結點位置有誤!"); return; } Node<T> A = new Node<T>(); if (i == 1) //刪除頭 { A = Head; Head = Head.Next; return; } Node<T> B = new Node<T>(); B = Head; int j = 1; while (B.Next != null && j < i) { A = B; B = B.Next; j++; } if (j == i) { A.Next = B.Next; } } /// <summary> /// 顯示單鏈表 /// </summary> public void Dispaly() { Node<T> A = new Node<T>(); A = Head; while (A != null) { Console.WriteLine(A.Data); A = A.Next; } } #region 面試題 /// <summary> /// 單鏈表反轉 /// </summary> public void Reverse() { if (GetLength()==1 || Head==null) { return; } Node<T> NewNode = null; Node<T> CurrentNode = Head; Node<T> TempNode = new Node<T>(); while (CurrentNode!=null) { TempNode = CurrentNode.Next; CurrentNode.Next = NewNode; NewNode = CurrentNode; CurrentNode = TempNode; } Head = NewNode; Dispaly(); } /// <summary> /// 得到單鏈表中間值 /// 思路:使用兩個指針,第一個每次走一步,第二個每次走兩步: /// </summary> public void GetMiddleValue() { Node<T> A = Head; Node<T> B = Head; while (B!=null && B.Next!=null) { A = A.Next; B = B.Next.Next; } if (B != null) //奇數 { Console.WriteLine("奇數:中間值爲:{0}", A.Data); } else //偶數 { Console.WriteLine("偶數:中間值爲:{0}和{1}", A.Data, A.Next.Data); } } #endregion }
static void Main(string[] args) { LinkList<string> link = new LinkList<string>(); link.Append("A"); link.Append("B"); link.Append("C"); link.Append("D"); link.Append("E"); link.Insert("Head", 1); Console.WriteLine("單鏈表內容:"); link.Dispaly(); link.Delete(5); Console.WriteLine("已完成刪除單鏈表中第5行記錄數"); link.Dispaly(); Console.WriteLine("查詢單鏈表中第1:{0}.第3:{1}", link.GetNodeValue(1), link.GetNodeValue(3)); Console.WriteLine("面試題-->單鏈表反轉"); link.Reverse(); Console.WriteLine("面試題-->得到單鏈表中間值"); link.GetMiddleValue(); }
輸出結果:code