链表
逻辑上相邻,物理上不一定相邻
头结点
1.统一首节点和其他节点插入,删除操作
2.防止链表空
分类
单链表,双链表,循环链表
单链表实现
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
namespace DataStruct.List
{
/// <summary>
/// 链表节点
/// </summary>
/// <typeparam name="T">数据类型</typeparam>
class Node<T>
{
/// <summary>
/// 数据域
/// </summary>
public T Data { get; set; }
/// <summary>
/// 引用域
/// </summary>
public Node<T> Next {get;set;}
/// <summary>
/// 构造器
/// </summary>
public Node(){}
/// <summary>
/// 节点构造器
/// </summary>
/// <param name="data">数据域</param>
/// <param name="next">引用域</param>
public Node(T data,Node<T> next=null)
{
this.Data = data;
this.Next = next;
}
/// <summary>
/// 覆盖ToString方法
/// </summary>
/// <returns>返回字符串</returns>
public override string ToString()
{
if (this.Next!=null)
return this.Data + "->";
else
return this.Data + "^";
}
}
/// <summary>
/// 链表辅助工具类
/// </summary>
/// <typeparam name="T">数据类型</typeparam>
static class LinkListUtil<T>
{
/// <summary>
/// 判断链表成环
/// </summary>
/// <param name="head">头结点</param>
/// <returns>返回是否成环</returns>
public static bool HasCycle(Node<T> head)
{
if (head == null || head.Next == null)
return false;
Node<T> p = head;
Node<T> q = head;
while(q!=null&&q.Next!=null)
{
p = p.Next;
q = q.Next.Next;
}
return false;
}
}
/// <summary>
/// 单链表
/// </summary>
/// <typeparam name="T">数据类型</typeparam>
class LinkList<T> : IList<T>, IEnumerable<T>
where T:IComparable<T>
{
/// <summary>
/// 获取头结点
/// </summary>
public Node<T> Head { get; }
/// <summary>
/// 节点数量
/// </summary>
private int count;
/// <summary>
/// 构造器
/// </summary>
public LinkList()
{
this.Head = new Node<T>();
}
/// <summary>
/// 构造器
/// </summary>
/// <param name="array">数组</param>
public LinkList(params T[]array)
{
Node<T> p = this.Head = new Node<T>();
foreach (var item in array)
{
Node<T> t = new Node<T>(item);
p.Next = t;
p = p.Next;
this.count++;
}
}
/// <summary>
/// 构造器
/// </summary>
/// <param name="array">数组</param>
/// <param name="reverse">是否使用尾插法</param>
public LinkList(IEnumerable<T> array, bool reverse = false)
{
if(reverse)
{
this.Head = new Node<T>();
foreach (var item in array)
{
Node<T> t = new Node<T>(item,Head.Next);
Head.Next = t;
this.count++;
}
}
else
{
Node<T> p = this.Head = new Node<T>();
foreach (var item in array)
{
Node<T> t = new Node<T>(item);
p.Next = t;
p = p.Next;
this.count++;
}
}
}
/// <summary>
/// 检查索引
/// </summary>
/// <param name="index">索引</param>
private void RaiseForIndex(ref int index)
{
if (index < 0)
index += this.count;
if (index < 0|| index >= count)
throw new IndexOutOfRangeException("列表索引访问越界了");
}
/// <summary>
/// 检查区间
/// </summary>
/// <param name="index">索引</param>
private void RaiseForRange(ref int start, ref int end)
{
if (start < 0) start += count;
if (end < 0) end += count;
var cnt = end - start;
if (start < 0 || end < 0 || cnt <= 0 || start >= count || end > count)
throw new IndexOutOfRangeException("列表索引访问越界了");
}
/// <summary>
/// 查找给定索引元素的前驱节点
/// </summary>
/// <param name="index">索引</param>
/// <returns>返回节点</returns>
public Node<T> FindPrevious(int index)
{
RaiseForIndex(ref index);
int i = 0;
Node<T> p = this.Head;
while (i < index && p.Next != null)
{
p = p.Next;
i++;
}
return p;
}
///// <summary>
///// 返回倒数第index个元素的节点
///// </summary>
///// <param name="index">倒数第几</param>
///// <returns>返回该节点</returns>
//public Node<T> FindLast(int index)
//{
// if(index<=0)
// throw new IndexOutOfRangeException("索引访问越界");
// Node<T> p= this.Head;
// for (int i = 0; i < index; i++)
// {
// if (p.Next == null)
// throw new IndexOutOfRangeException("索引访问越界");
// p = p.Next;
// }
// Node<T> q = this.Head;
// while(p.Next!=null)
// {
// p = p.Next;
// q = q.Next;
// }
// return q.Next;
//}
/// <summary>
/// 索引器
/// </summary>
/// <param name="index">索引值</param>
/// <returns>返回对应数据</returns>
public T this[int index]
{
get
{
return FindPrevious(index).Next.Data;
}
set
{
FindPrevious(index).Next.Data= value;
}
}
/// <summary>
/// 节点数量
/// </summary>
public int Count => this.count;
/// <summary>
/// 增加元素
/// </summary>
/// <param name="val">元素变量</param>
public void Add(T val)
{
Node<T> p = this.Head;
while (p.Next != null)
p = p.Next;
p.Next = new Node<T>(val,null);
this.count++;
}
/// <summary>
/// 清理
/// </summary>
public void Clear()
{
this.Head.Next = null;
this.count = 0;
}
/// <summary>
/// 查看数据在列表中的位置
/// </summary>
/// <param name="val">数据</param>
/// <returns>返回索引</returns>
public int? IndexOf(T val)
{
int i = 0;
var p= this.Head;
while(i<this.count)
{
p = p.Next;
if (p.Data.CompareTo(val) == 0)
return i;
i++;
}
return null;
}
/// <summary>
/// 插入元素
/// </summary>
/// <param name="index">元素索引</param>
/// <param name="val">插入元素值</param>
public void Insert(int index, T val)
{
var p=this.FindPrevious(index);
Node<T> temp = new Node<T>(val,p.Next);
p.Next = temp;
this.count++;
}
/// <summary>
/// 判断列表是否包含某个元素
/// </summary>
/// <param name="val">元素</param>
/// <returns>返回是否包含</returns>
public bool IsContains(T val) => this.IndexOf(val) != null;
/// <summary>
/// 判空
/// </summary>
/// <returns>表是否为空</returns>
public bool IsEmpty()=>this.Head.Next==null;
/// <summary>
/// 删除元素
/// </summary>
/// <param name="index">元素索引</param>
/// <returns>返回要删除的元素</returns>
public T Remove(int index)
{
var p = this.FindPrevious(index);
var q = p.Next;
var temp = q.Data;
p.Next = q.Next;
this.count--;
return temp;
}
/// <summary>
/// 覆盖ToString方法
/// </summary>
/// <returns>返回字符串</returns>
public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.Append("[");
Node<T> p = this.Head;
while(p.Next!=null)
{
p = p.Next;
sb.Append(p);
}
sb.Append("]");
return sb.ToString();
}
/// <summary>
/// 转化为数组
/// </summary>
/// <returns>数组</returns>
public T[] ToArray()
{
T[] array = new T[count];
int i = 0;
foreach (var item in this)
array[i++] = item;
return array;
}
/// <summary>
/// 隐式类型转换
/// </summary>
/// <param name="array">顺序表</param>
public static explicit operator LinkList<T>(SequenceList<T> ls)=>new LinkList<T>(ls.ToArray());
/// <summary>
/// 显式类型转换
/// </summary>
/// <param name="array">数组</param>
public static implicit operator LinkList<T>(T[] array) => new LinkList<T>(array);
/// <summary>
/// 获取迭代器
/// </summary>
/// <returns>返回迭代器</returns>
public IEnumerator<T> GetEnumerator()
{
var p = this.Head;
while(p.Next!=null)
{
p = p.Next;
yield return p.Data;
}
}
/// <summary>
/// 获取迭代器
/// </summary>
/// <returns>返回迭代器</returns>
IEnumerator IEnumerable.GetEnumerator()
{
var p = this.Head;
while (p.Next != null)
{
p = p.Next;
yield return p.Data;
}
}
/// <summary>
/// 范围添加
/// </summary>
/// <param name="collection">可迭代集合</param>
public void AddRange(IEnumerable<T> collection)
{
Node<T> p = this.FindPrevious(this.count-1).Next;
foreach (var item in collection)
{
p.Next= new Node<T>(item, null);
p = p.Next;
this.count++;
}
}
/// <summary>
/// 范围移除
/// </summary>
/// <param name="start">开始索引</param>
/// <param name="end">结束索引</param>
public void RemoveRange(int start, int end)
{
RaiseForRange(ref start,ref end);
Node<T> pstart = this.FindPrevious(start);
Node<T> pend = this.FindPrevious(end-1);
pstart.Next = pend.Next.Next;
}
/// <summary>
/// 链表1复制到链表2
/// </summary>
/// <param name="t1">顺序表1</param>
/// <param name="t2">顺序表2</param>
/// <param name="start">开始索引</param>
/// <param name="end">结束索引</param>
public static bool TryCopy(LinkList<T> t1,out LinkList<T> t2,int start,int end)
{
if (start < 0) start += t1.count;
if (end < 0) end += t1.count;
var cnt = end - start;
if (start < 0 || end < 0 || cnt <= 0 || start >= t1.count || end > t1.count)
{
t2 = null;
return false;
}
t2 = new LinkList<T>();
Node<T> q = t2.Head, p = t1.FindPrevious(start);
while(p.Next!=null&& start < end)
{
p = p.Next;
q.Next= new Node<T>(p.Data, null);
q = q.Next;
start++;
}
return true;
}
/// <summary>
/// 链表切片
/// </summary>
/// <param name="start">开始索引</param>
/// <param name="end">结束索引</param>
/// <returns>切片结果</returns>
public LinkList<T> this[(int start, int end) t]
{
get
{
TryCopy(this, out LinkList<T> ans, t.start, t.end);
return ans;
}
}
/// <summary>
/// 链表切片
/// </summary>
/// <param name="start">开始索引</param>
/// <param name="end">结束索引</param>
/// <param name="step">结束索引</param>
/// <returns>切片结果</returns>
public LinkList<T> this[(int start, int end,int step) t]
{
get
{
if (t.step <= 0)
throw new IndexOutOfRangeException("列表索引访问越界了");
RaiseForRange(ref t.start, ref t.end);
var ls = new LinkList<T>();
Node<T> q = ls.Head, p =this.FindPrevious(t.start);
int i = 0;
int cnt = 0;
while (p.Next != null && i < t.end)
{
p = p.Next;
if(cnt==t.step||i==t.start)
{
q.Next = new Node<T>(p.Data, null);
q = q.Next;
cnt = 0;
}
i++;
cnt++;
}
return ls;
}
}
/// <summary>
/// 删除列表顶部元素
/// </summary>
/// <returns>返回被删除的元素值</returns>
public T Pop()
{
Node<T> p = this.FindPrevious(this.count - 1);
Node<T> q = p.Next;
p.Next = q.Next;
var temp = q.Data;
this.count--;
return temp;
}
/// <summary>
/// 逆置
/// </summary>
public void Reverse()
{
Node<T> p = this.Head.Next,q = null, t=null;
while(p!=null)
{
t = p.Next;
p.Next = q;
q = p;
p = t;
}
this.Head.Next = q;
}
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。