C#數據結構與演算法系列(四):鏈表——單鏈表(Single-LinkedList)
1.介紹:
鏈表是有序的列表,但是它在記憶體的存儲如下:
鏈表是以節點的方式來存儲,鏈式存儲
每一個節點包含data域,next域:指向下一個節點
鏈表的各個節點不一定是連續存儲
鏈表分帶頭節點的鏈表和不帶頭節點的鏈表,根據實際的需求來確定
單鏈表(帶頭節點)
2.應用實例
使用帶head頭的單向鏈表實現 –水滸英雄排行榜管理完成對英雄人物的增刪改查操作
第一種方法在添加英雄時,直接添加到鏈表的尾部
第二種方式在添加英雄時,根據排名將英雄插入到指定位置
(如果有這個排名,則添加失敗,並給出提示)
第一種方式思路
第二種思路
刪除思路
程式碼:
public class HeroNode { public HeroNode(int id, string name, string nickName) { this.Id = id; this.Name = name; this.NickName = nickName; } public int Id { get; set; } public string Name { get; set; } public string NickName { get; set; } public HeroNode Next { get; set; } public override string ToString() { return base.ToString(); } }
public class SingleLinkedList { private HeroNode head = null; public SingleLinkedList() { //初始化頭節點,頭節點不要動,不存放具體的數據 head = new HeroNode(0, "", ""); } /// <summary> /// 添加節點 /// </summary> /// <param name="heroNode"></param> public void Add(HeroNode heroNode) { //因為head節點不能動,因此我們需要一個輔助遍歷temp var temp = head; while (true) { //找到鏈表的最後 if (temp.Next == null) break; temp = temp.Next; } //當退出while循環時,temp就指向了鏈表的最後 //將最後的這個節點的next指向新的節點 temp.Next = heroNode; } /// <summary> /// 按Id順序添加節點 /// </summary> /// <param name="heroNode"></param> public void AddById(HeroNode heroNode) { //因為頭節點不能動,因此我們仍然通過一個輔助指針(變數)來幫助找到添加的位置 //因為是單鏈表,我們找的temp是位於添加位置的前一個節點,否則插入不了 var temp = head; //定義一個flag,標誌添加的Id是否存在,默認為false bool flag = false; while (true) { //說明temp已經在鏈表的最後 if (temp.Next == null) break; //位置找到,就在temp的後面插入 if (temp.Next.Id > heroNode.Id) break; //說明希望存入的節點已存在 if (temp.Next.Id == heroNode.Id) { //說明Id已經存在 flag = true; break; } //後移,遍歷當前鏈表 temp = temp.Next; } //說明Id已經存在 if (flag) Console.WriteLine($"{heroNode.Id}節點已存在"); else { //把原本存在的節點,存入新的節點後面 heroNode.Next = temp.Next; //把新的節點插入到鏈表中,temp後面 temp.Next = heroNode; } } /// <summary> /// 更新節點 /// </summary> /// <param name="heroNode"></param> public void Update(HeroNode heroNode) { var temp = head.Next; bool flag = false; //if (temp == null) Console.WriteLine("鏈表為空"); //else //{ while (true) { if (temp == null) break; //找到節點 if (temp.Id==heroNode.Id) { flag = true; break; } temp = temp.Next; } if (flag) { temp.Name = heroNode.Name; temp.NickName = heroNode.NickName; } else Console.WriteLine($"沒有找到Id:{heroNode.Id}的節點"); //} } /// <summary> /// 刪除節點 /// </summary> /// <param name="id"></param> public void Delete(int id) { var temp = head; bool flag = false; while (true) { if (temp.Next == null) break; //已經到了鏈表的最後 //找到待刪除節點的前一個節點 if(temp.Next.Id==id) { flag = true; break; } temp = temp.Next; } //將待刪除的前一個節點前指向待刪除的後一個節點 if (flag) temp.Next = temp.Next.Next; else Console.WriteLine("未找到節點"); } public void GetList() { var temp = head.Next; //if (temp == null) Console.WriteLine("鏈表為空"); //else //{ while (true) { if (temp == null) break; Console.WriteLine($"id={temp.Id},name={temp.Name},nickName={temp.NickName}"); temp = temp.Next; } //} } public static void Test() { HeroNode heroNode1 = new HeroNode(1, "宋江", "及時雨"); HeroNode heroNode2 = new HeroNode(2, "盧俊義", "玉麒麟"); HeroNode heroNode3 = new HeroNode(3, "吳用", "智多星"); HeroNode heroNode4 = new HeroNode(4, "林沖", "豹子頭"); SingleLinkedList singleLinkedList = new SingleLinkedList(); //singleLinkedList.Add(heroNode1); //singleLinkedList.Add(heroNode2); //singleLinkedList.Add(heroNode3); //singleLinkedList.Add(heroNode4); singleLinkedList.AddById(heroNode1); singleLinkedList.AddById(heroNode4); singleLinkedList.AddById(heroNode3); singleLinkedList.AddById(heroNode2); singleLinkedList.Delete(3); singleLinkedList.Update(new HeroNode(2, "李逵", "黑旋風")); singleLinkedList.GetList(); } }