5,泛型单链表
链表反转实现思路:
1)不要试图在原来链表试图修剪,比较容易掉坑,避免链表断裂
2)新建一个表头rverseHeader,只要用来反转前后节点地址指向,也是新链表头
3)新建临时节点,curNode移到当前节点,nexNode移到下一节点防止链表断裂
4)从旧链表往下查找,断开当然节点,并设置curNode.Next = rverseHeader.Next,新头指定当前节点rverseHeader.Next = curNode
5)旧头节点Header.Next 重新指向rverseHeader.Next
C#代码实现:
1 using System; 2 3 namespace 数据结构 4 { 5 public class Linked<T> 6 { 7 //头部节点 8 private Node Header { get; } = new Node(0, default); 9 10 //添加到链表末尾 11 public void Append(Node node) 12 { 13 //临时节点,从指向头部节点开始查找 14 Node temp = this.Header; 15 //下节点为空才链表结尾 16 while (temp.Next != null) 17 { 18 //指向下一个节点 19 temp = temp.Next; 20 } 21 //加到末尾 22 temp.Next = node; 23 } 24 25 //插入节点 26 public void Insert(Node node) 27 { 28 //临时节点,从指向头部节点开始查找 29 Node temp = this.Header; 30 //下节点不为空继续向下查找 31 while (temp.Next != null) 32 { 33 if (node.Index < temp.Next.Index) 34 { 35 //如果小于下一个节点就插到下一个节点前面 36 node.Next = temp.Next; 37 temp.Next = node; 38 return; 39 } 40 else if (node.Index == temp.Next.Index) 41 { 42 //如果等于下一个节点,节点以存在返回 43 Console.WriteLine($"节点{node.Index}已经存在"); 44 return; 45 } 46 //继续查找 47 temp = temp.Next; 48 } 49 //插入末尾 50 temp.Next = node; 51 } 52 53 //移除节点 54 public void Remove(int index) 55 { 56 //临时节点,从指向头部节点开始查找 57 Node temp = this.Header; 58 //下一节点不为空继续往下找 59 while (temp.Next != null) 60 { 61 if (temp.Next.Index == index) 62 { 63 //找到,Next 指向下下个节点 64 temp.Next = temp.Next.Next; 65 return; 66 } 67 else 68 { 69 //继续查找 70 temp = temp.Next; 71 } 72 } 73 Console.WriteLine($"没找节点{index}"); 74 } 75 76 //反转列表 77 public void Rverse() 78 { 79 //指向当前节点 80 Node curNode = this.Header.Next; 81 //当断开当前节点时,指向下一节点,避免链表断开 82 Node nexNode = null; 83 //新表头 84 Node rverseHeader = new Node(0, default); 85 //只有一个元素不用处理 86 if (Header.Next == null || Header.Next.Next == null) 87 { 88 return; 89 } 90 while (curNode != null) 91 { 92 //指向下一节点 93 nexNode = curNode.Next; 94 //断开当前节点,并指向上一节点地址,当第一次进入上节点地址为空 95 curNode.Next = rverseHeader.Next; 96 //头节点指向当前节点 97 rverseHeader.Next = curNode; 98 //指向下节点 99 curNode = nexNode; 100 } 101 //旧节点头重新指向反转后第一个元素 102 Header.Next = rverseHeader.Next; 103 } 104 105 //打印所有节点 106 public void Scan() 107 { 108 //建立临时节点,从指向头部节点开始查找 109 Node temp = this.Header; 110 while (temp.Next != null) 111 { 112 Console.WriteLine(temp.Next.ToString()); 113 //临时节点指向下一节点 114 temp = temp.Next; 115 } 116 } 117 118 //链表节点 119 public class Node 120 { 121 public int Index { get; set; } 122 public T Value { get; set; } 123 public Node Next { get; set; } 124 public Node(int index, T val) 125 { 126 this.Index = index; 127 this.Value = val; 128 } 129 //重写Tostring方法方便查看 130 public override string ToString() 131 { 132 return $"index={Index},value={Value}"; 133 } 134 } 135 } 136 137 public class LinkedListDemo 138 { 139 static void Main(string[] agrs) 140 { 141 Console.WriteLine("向链表添加三位骨架精奇同志"); 142 var Linked = new Linked<string>(); 143 Linked.Append(new Linked<string>.Node(2, "张三")); 144 Linked.Append(new Linked<string>.Node(5, "李四")); 145 Linked.Append(new Linked<string>.Node(4, "王五")); 146 Linked.Scan(); 147 //--------------------------------------------------- 148 Console.WriteLine("删除王五"); 149 Linked.Remove(4); 150 Linked.Scan(); 151 //--------------------------------------------------- 152 Console.WriteLine("插入小明"); 153 Linked.Insert(new Linked<string>.Node(4, "小明")); 154 Linked.Scan(); 155 Console.WriteLine("插入小李"); 156 Linked.Insert(new Linked<string>.Node(1, "小李")); 157 Linked.Scan(); 158 //--------------------------------------------------- 159 Console.WriteLine("反转链表"); 160 Linked.Rverse(); 161 Linked.Scan(); 162 } 163 } 164 }