什么是链表
链表由若干节点构成,节点之间有链接,链接末尾没有节点,指向空null.
链表的实现需要定义:
- 泛型变量作为节点数据;
- 下一个节点的引用;
- 头节点。
代码实现单链表
using System; using System.Text;
namespace AlgorithmTest08_链表 { public class LinkedList1<T> { private class Node { public T t; public Node next; public Node(T t, Node next) { this.t = t; this.next = next; } public Node(T t) { this.t = t; this.next = null; } public override string ToString() { return t.ToString(); } }
private Node head;
private int N;
public LinkedList1() { head = null; N = 0; } public int Count { get { return N; } } public bool IsEmpty { get { return N == 0; } } public void Add(int index, T t) { if (index < 0 || index > N) { throw new ArgumentException("非法索引"); } if (index == 0) { head = new Node(t, head); } else { Node pre = head; for (int i = 0; i < index - 1; i++) { pre = pre.next; } pre.next = new Node(t, pre.next); } N++; } public void AddFirst(T t) { Add(0, t); }
public void AddLast(T t) { Add(N, t); } public T Get(int index) { if (index < 0 || index >= N) { throw new ArgumentException("非法索引"); } Node cur = head; for (int i = 0; i < index; i++) { cur = cur.next; } return cur.t; } public T GetFirst() { return Get(0); } public T GetLast() { return Get(N - 1); } public void Set(int index, T newT) { if (index < 0 || index >= N) { throw new ArgumentException("非法索引"); } Node cur = head; for (int i = 0; i < index; i++) { cur = cur.next; } cur.t = newT; } public bool Contains(T t) { Node cur = head; while (cur != null) { if (cur.t.Equals(t)) { return true; } cur = cur.next; } return false; } public T RemoveAt(int index) { if (index < 0 || index >= N) { throw new ArgumentException("索引不合法"); } if (index == 0) { Node delNode = head; head = head.next; N--; return delNode.t; } else { Node pre = head; for (int i = 0; i < index - 1; i++) { pre = pre.next; } Node delNode = pre.next; pre.next = delNode.next; N--; return delNode.t; } } public T RemoveFirst() { return RemoveAt(0); } public T RemoveLast() { return RemoveAt(N - 1); }
public void Remove(T t) { if (head == null) { return; } if (head.t.Equals(t)) { RemoveFirst(); } else { Node cur = head; Node pre = null; while (cur != null) { if (cur.t.Equals(t)) { break; } pre = cur; cur = cur.next; } if (cur != null) { pre.next = pre.next.next; N--; } } }
public override string ToString() { StringBuilder res = new StringBuilder(); Node cur = head; while (cur != null) { res.Append(cur + "->"); cur = cur.next; } res.Append("null"); return res.ToString(); } } }
|
链表添加数据(带头节点)
若是在头节点添加,就是新节点的next指向头节点,然后新节点赋值给head,自己成为新的头节点。
若是正常添加新节点,就是index位-1进行循环遍历。移动定位节点到位置的前一个,然后定位节点的next指向新节点的next,新节点本身指向定位节点的next,成功插入。
代码实现:
public void Add(int index, T t) { if (index < 0 || index > N) { throw new ArgumentException("非法索引"); } if (index == 0) { head = new Node(t, head); } else { Node pre = head; for (int i = 0; i < index - 1; i++) { pre = pre.next; } pre.next = new Node(t, pre.next); } N++; } public void AddFirst(T t) { Add(0, t); } public void AddLast(T t) { Add(N, t); }
|
重写ToString
public override string ToString() { StringBuilder res = new StringBuilder(); Node cur = head; while (cur != null) { res.Append(cur + "->"); cur = cur.next; } res.Append("null"); return res.ToString(); }
|
测试:
class Program { static void Main(string[] args) { LinkedList1<int> l = new LinkedList1<int>(); Console.WriteLine("初次打印"); for (int i = 0; i < 5; i++) { l.AddFirst(i); Console.WriteLine(l); } Console.WriteLine("末尾添加数字99:"); l.AddLast(99); Console.WriteLine(l); Console.WriteLine("索引2添加222"); l.Add(2, 2222222); Console.WriteLine(l); Console.WriteLine("查询索引2"); Console.WriteLine(l.Get(2)); Console.WriteLine("修改索引2"); l.Set(2, 20); Console.WriteLine(l.Get(2)); Console.WriteLine("查找链表中是否有值"); Console.WriteLine(l.Contains(4)); Console.ReadKey(); } }
|
删除元素
头部:head.next指向下一个即可,其他部分:index前一个.next指向index.next
public T RemoveAt(int index) { if (index < 0 || index >= N) { throw new ArgumentException("索引不合法"); } if (index == 0) { Node delNode = head; head = head.next; N--; return delNode.t; } else { Node pre = head; for (int i = 0; i < index - 1; i++) { pre = pre.next; } Node delNode = pre.next; pre.next = delNode.next; N--; return delNode.t; } }
|
测试结果: