C# 数组集合<二> 双向链表和双向循环链表
2016-09-22 16:15
549 查看
前情提示:
上一篇总结了数据结构的基本概念,以及在C#下的一些基本实现Code。从这篇之后难度加大,代码量也增大了。分卷了。这一篇主要讲述双向链表和双向循环链表。双向链表:
双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。双向循环链表:
双向循环链表是另一种形式的链式存贮结构。它的特点是表中最后一个结点的指针域指向头结点,整个链表形成一个环。节点类(DoubleLinkedListNode.cs)
public class DoubleLinkedListNode<T> { //前驱 private DoubleLinkedListNode<T> _nextDoubleLinkedListNode; private DoubleLinkedListNode<T> _prevDoubleLinkedListNode; //数据 private T dataValue; /// <summary> /// 无参构造函数 该节点只有默认值,前驱和后继都 ——>null /// </summary> public DoubleLinkedListNode() { this.dataValue = default(T); this._nextDoubleLinkedListNode = null; this._prevDoubleLinkedListNode = null; } /// <summary> /// 构造方法:实例化该节点只有传入的data域,前驱和后继都指向null /// </summary> /// <param name="value"></param> public DoubleLinkedListNode(T value) { this._prevDoubleLinkedListNode = null; this.dataValue = value; this._nextDoubleLinkedListNode = null; } /// <summary> /// 构造函数:实例化一个正常的Node 数据域 前驱后继都有值 /// </summary> /// <param name="value"></param> /// <param name="prev"></param> /// <param name="next"></param> public DoubleLinkedListNode(T value, DoubleLinkedListNode<T> prev, DoubleLinkedListNode<T> next) { this._prevDoubleLinkedListNode = prev; this.dataValue = value; this._nextDoubleLinkedListNode = next; } public DoubleLinkedListNode<T> PrevDoubleLinkedListNode { get { return this._prevDoubleLinkedListNode; } set { this._prevDoubleLinkedListNode = value; } } public T DataValue { get { return this.dataValue; } set { this.dataValue = value; } } public DoubleLinkedListNode<T> NextDoubleLinkedListNode { get { return this._nextDoubleLinkedListNode; } set { this._nextDoubleLinkedListNode = value; } } /// <summary> /// Show 方法,调试用 /// </summary> /// <returns></returns> public override string ToString() { T p = this._prevDoubleLinkedListNode == null ? default(T) : this._prevDoubleLinkedListNode.dataValue; T n = this._nextDoubleLinkedListNode == null ? default(T) : this._nextDoubleLinkedListNode.dataValue; string s = string.Format("Data:{0},Prev:{1},Next:{2}", this.dataValue, p, n); return s; } }
接口(ILinkList.cs)
internal interface ILinkedList<T> { /// <summary> /// 头元素 /// </summary> DoubleLinkedListNode<T> HeadDoubleLinkedListNode { get; } /// <summary> /// 尾元素 /// </summary> DoubleLinkedListNode<T> EndDoubleLinkedListNode { get; } /// <summary> /// 在 LinkedList<(Of <(T>)>) 中指定的现有节点后添加指定的新节点。 /// </summary> /// <param name="node"></param> /// <param name="newNode"></param> void AddAfter(DoubleLinkedListNode<T> node, DoubleLinkedListNode<T> newNode); /// <summary> /// 在 LinkedList<(Of <(T>)>) 中的现有节点后添加新的节点或值。 /// </summary> /// <param name="node"></param> /// <param name="t"></param> void AddAfter(DoubleLinkedListNode<T> node, T t); /// <summary> /// 在 LinkedList<(Of <(T>)>) 中指定的现有节点前添加指定的新节点。 /// </summary> /// <param name="node"></param> /// <param name="newNode"></param> void AddBefore(DoubleLinkedListNode<T> node, DoubleLinkedListNode<T> newNode); /// <summary> /// 在 LinkedList<(Of <(T>)>) 中指定的现有节点前添加包含指定值的新节点。 /// </summary> /// <param name="node"></param> /// <param name="t"></param> void AddBefore(DoubleLinkedListNode<T> node, T t); /// <summary> /// 在 LinkedList<(Of <(T>)>) 的开头处添加包含指定值的新节点。 /// </summary> /// <param name="value"></param> /// <returns></returns> DoubleLinkedListNode<T> AddFirst(T value); /// <summary> /// 在 LinkedList<(Of <(T>)>) 的开头处添加指定的新节点 /// </summary> /// <param name="node"></param> void AddFirst(DoubleLinkedListNode<T> node); /// <summary> /// 在 LinkedList<(Of <(T>)>) 的结尾处添加包含指定值的新节点。 /// </summary> /// <param name="value"></param> /// <returns></returns> DoubleLinkedListNode<T> AddLast(T value); /// <summary> /// 在 LinkedList<(Of <(T>)>) 的结尾处添加指定的新节点 /// </summary> /// <param name="node"></param> void AddLast(DoubleLinkedListNode<T> node); /// <summary> /// 从 LinkedList<(Of <(T>)>) 中移除指定的节点。 /// </summary> /// <param name="node"></param> bool Remove(DoubleLinkedListNode<T> node); /// <summary> /// 从 LinkedList<(Of <(T>)>) 中按索引删除节点。 /// </summary> /// <param name="node"></param> bool Remove(int index); /// <summary> /// 移除头结点 /// </summary> void RemoveHeadNode(); /// <summary> /// 移除尾节点 /// </summary> void RemoveEndNode(); /// <summary> /// 从 LinkedList<(Of <(T>)>) 中查找第一个匹配项 /// </summary> 4000 ; /// <param name="value"></param> /// <returns></returns> DoubleLinkedListNode<T> Find(T value); /// <summary> /// 从 LinkedList<(Of <(T>)>) 中查找最后一个匹配项 /// </summary> /// <param name="value"></param> /// <returns></returns> DoubleLinkedListNode<T> FindLast(T value); /// <summary> /// 查询元素的索引 /// </summary> /// <param name="item"></param> /// <returns></returns> int IndexOf(T item); /// <summary> /// 能过索引得到元素的元素 /// </summary> /// <param name="index"></param> /// <returns></returns> T GetElementByIndex(int index); /// <summary> /// 通过索引得到节点对象 /// </summary> /// <param name="index"></param> /// <returns></returns> DoubleLinkedListNode<T> GetNodeByIndex(int index); }
双向链表类(DoubleLinkList.cs)
public class DoubleLinkedList<T> : ILinkedList<T> { //前驱 //后置 private DoubleLinkedListNode<T> _endDoubleLinkedListNode; private DoubleLinkedListNode<T> _headDoubleLinkedListNode; //长度 private int size; /// <summary> /// 判断链表是否是空的 /// </summary> public bool IsEmpty { get { return this._headDoubleLinkedListNode == null; } } /// <summary> /// 链表中元素的个数 /// </summary> public int Count { get { int i = 0; DoubleLinkedListNode<T> node = this._headDoubleLinkedListNode; while (node != null) { ++ i; node = node.NextDoubleLinkedListNode; } return i; //return this.size; } } /// <summary> /// 根据索引获取链表中的节点 /// </summary> /// <param name="index">整型索引</param> /// <returns>节点</returns> public DoubleLinkedListNode<T> this[int index] { get { //链表头节点是空的 if (this._headDoubleLinkedListNode == null) { throw new Exception("链表是空的。"); } //索引过小 if (index < 0) { throw new IndexOutOfRangeException(); } //索引过大 if (index >= this.Count) { throw new IndexOutOfRangeException(); } //取得头节点 var current = new DoubleLinkedListNode<T>(); //current = head; //int i = 0; ////遍历链表 //while (true) //{ // //找到第index个节点 // if (i == index) // { // break; // } // current = current.Next; // i++; //} //return current; //如果索引在前一半,那么从前向后找 if (index < this.size/2) { current = this._headDoubleLinkedListNode; int i = 0; //遍历链表 while (true) { //找到第index个节点 if (i == index) { break; } current = current.NextDoubleLinkedListNode; i++; } return current; } else //如果索引在后一半,那么从后向前找 { current = this._endDoubleLinkedListNode; int i = this.size; //遍历链表 while (true) { //找到第index个节点 if (i == index) { break; } current = current.PrevDoubleLinkedListNode; i--; } return current.NextDoubleLinkedListNode; } } } public DoubleLinkedListNode<T> HeadDoubleLinkedListNode { get { return this._headDoubleLinkedListNode; } set { this._headDoubleLinkedListNode = value; } } public DoubleLinkedListNode<T> EndDoubleLinkedListNode { get { return this._endDoubleLinkedListNode; } set { this._endDoubleLinkedListNode = value; } } public void AddAfter(DoubleLinkedListNode<T> node, DoubleLinkedListNode<T> newNode) { this.AddAfter(node, newNode.DataValue); } public void AddAfter(DoubleLinkedListNode<T> node, T t) { if (node == null || t == null) { throw new Exception("元素为空,不可以进行插入"); } int index = this.IndexOf(node.DataValue); if (index != -1) { DoubleLinkedListNode<T> currNode = this.GetNodeByIndex(index); DoubleLinkedListNode<T> upNode = currNode.PrevDoubleLinkedListNode; DoubleLinkedListNode<T> nextNode = currNode.NextDoubleLinkedListNode; var newNode = new DoubleLinkedListNode<T>(t); if (index == 0) { this._headDoubleLinkedListNode.NextDoubleLinkedListNode = newNode; newNode.PrevDoubleLinkedListNode = this._headDoubleLinkedListNode; newNode.NextDoubleLinkedListNode = nextNode; } else if (index == this.Count - 1) { newNode.PrevDoubleLinkedListNode = this._endDoubleLinkedListNode; this._endDoubleLinkedListNode.NextDoubleLinkedListNode = newNode; this._endDoubleLinkedListNode = newNode; } else { nextNode.PrevDoubleLinkedListNode = newNode; currNode.NextDoubleLinkedListNode = newNode; newNode.PrevDoubleLinkedListNode = currNode; newNode.NextDoubleLinkedListNode = nextNode; } } } public void AddBefore(DoubleLinkedListNode<T> node, DoubleLinkedListNode<T> newNode) { this.AddBefore(node, newNode.DataValue); } public void AddBefore(DoubleLinkedListNode<T> node, T t) { if (node == null || t == null) { throw new Exception("元素为空,不可以进行插入"); } int index = this.IndexOf(node.DataValue); if (index != -1) { DoubleLinkedListNode<T> currNode = this.GetNodeByIndex(index); DoubleLinkedListNode<T> upNode = currNode.PrevDoubleLinkedListNode; DoubleLinkedListNode<T> nextNode = currNode.NextDoubleLinkedListNode; var newNode = new DoubleLinkedListNode<T>(t); if (index == 0) { this._headDoubleLinkedListNode.PrevDoubleLinkedListNode = newNode; newNode.NextDoubleLinkedListNode = this._headDoubleLinkedListNode; this._headDoubleLinkedListNode = newNode; } else if (index == this.Count - 1) { upNode.NextDoubleLinkedListNode = newNode; newNode.NextDoubleLinkedListNode = this._endDoubleLinkedListNode; this._endDoubleLinkedListNode.PrevDoubleLinkedListNode = newNode; } else { upNode.NextDoubleLinkedListNode = newNode; nextNode.PrevDoubleLinkedListNode = newNode; currNode.PrevDoubleLinkedListNode = upNode; currNode.NextDoubleLinkedListNode = nextNode; } } } /// <summary> /// 添加节点到链表的开头 /// </summary> /// <param name="t"></param> public DoubleLinkedListNode<T> AddFirst(T value) { var doubleLinkedListNode = new DoubleLinkedListNode<T>(value); //如果头为null if (this._headDoubleLinkedListNode == null) { //把头节点设置为node this._headDoubleLinkedListNode = doubleLinkedListNode; //因为是空链表,所以头尾一致 this._endDoubleLinkedListNode = doubleLinkedListNode; //大小加一 this.size++; return doubleLinkedListNode; } //原来头节点的上一个为新节点 this._headDoubleLinkedListNode.PrevDoubleLinkedListNode = doubleLinkedListNode; //新节点的下一个为原来的头节点 doubleLinkedListNode.NextDoubleLinkedListNode = this._headDoubleLinkedListNode; //新头节点为新节点 this._headDoubleLinkedListNode = doubleLinkedListNode; //大小加一 this.size++; return this._headDoubleLinkedListNode; } public void AddFirst(DoubleLinkedListNode<T> node) { this.AddFirst(node.DataValue); } /// <summary> /// 添加节点到链表的末尾 /// </summary> /// <param name="t">要添加的数据</param> public DoubleLinkedListNode<T> AddLast(T t) { var doubleLinkedListNode = new DoubleLinkedListNode<T>(t); //如果头为null if (this._headDoubleLinkedListNode == null) { //把头节点设置为node this._headDoubleLinkedListNode = doubleLinkedListNode; //因为是空链表,所以头尾一致 this._endDoubleLinkedListNode = doubleLinkedListNode; //大小加一 this.size++; return doubleLinkedListNode; } //将原尾节点的下一个设置为新节点 this._endDoubleLinkedListNode.NextDoubleLinkedListNode = doubleLinkedListNode; //将新节点的上一个设置为原尾节点 doubleLinkedListNode.PrevDoubleLinkedListNode = this._endDoubleLinkedListNode; //将尾节点重新设置为新节点 this._endDoubleLinkedListNode = doubleLinkedListNode; //大小加一 this.size++; return this._endDoubleLinkedListNode; } public void AddLast(DoubleLinkedListNode<T> node) { this.AddLast(node.DataValue); } /// <summary> /// 移除链表中的节点 /// </summary> /// <param name="index">要移除的节点的索引</param> public bool Remove(DoubleLinkedListNode<T> node) { if (node == null) { throw new Exception("节点不可以为空,无法进行删除"); } int index = this.IndexOf(node.DataValue); return this.Remove(index); } public bool Remove(int index) { if (index < 0 || index >= this.Count) { throw new Exception("索引值非法,无法进行删除。"); } bool flag = false; DoubleLinkedListNode<T> node = this._headDoubleLinkedListNode; int i = 0; while (node != null) { if (i == index) { DoubleLinkedListNode<T> upNode = node.PrevDoubleLinkedListNode; DoubleLinkedListNode<T> nextNode = node.NextDoubleLinkedListNode; if (index == 0) { this._headDoubleLinkedListNode = node.NextDoubleLinkedListNode; node = null; } else if (index == this.Count - 1) { this._endDoubleLinkedListNode = upNode; this._endDoubleLinkedListNode.NextDoubleLinkedListNode = null; node = null; } else { upNode.NextDoubleLinkedListNode = nextNode; nextNode.PrevDoubleLinkedListNode = upNode; node = null; } flag = true; break; } node = node.NextDoubleLinkedListNode; ++i; } return flag; } /// <summary> /// 移除头节点 /// </summary> public void RemoveHeadNode() { //链表头节点是空的 if (this.IsEmpty) { throw new Exception("链表是空的。"); } //如果size为1,那就是清空链表。 if (this.size == 1) { this.Clear(); return; } //将头节点设为原头结点的下一个节点,就是下一个节点上移 this._headDoubleLinkedListNode = this._headDoubleLinkedListNode.NextDoubleLinkedListNode; //处理上一步遗留问题,原来的第二个节点的上一个是头结点,现在第二个要变成头节点,那要把它的Prev设为null才能成为头节点 this._headDoubleLinkedListNode.PrevDoubleLinkedListNode = null; //大小减一 this.size--; } /// <summary> /// 移除尾节点 /// </summary> public void RemoveEndNode() { //链表头节点是空的 if (this.IsEmpty) { throw new Exception("链表是空的。"); } //如果size为1,那就是清空链表。 if (this.size == 1) { this.Clear(); return; } //尾节点设置为倒数第二个节点 this._endDoubleLinkedListNode = this._endDoubleLinkedListNode.PrevDoubleLinkedListNode; //将新尾节点的Next设为null,表示它是新的尾节点 this._endDoubleLinkedListNode.NextDoubleLinkedListNode = null; //大小减一 this.size--; } public DoubleLinkedListNode<T> Find(T value) { throw new NotImplementedException(); } public DoubleLinkedListNode<T> FindLast(T value) { throw new NotImplementedException(); } public int IndexOf(T item) { if (ite 12e11 m == null || this.Count == 0 || this._headDoubleLinkedListNode == null) { throw new Exception("无法得到元素索引"); } int reInt = -1; int i = 0; DoubleLinkedListNode<T> node = this._headDoubleLinkedListNode; while (node != null) { if (node.DataValue.Equals(item)) { reInt = i; break; } ++i; node = node.NextDoubleLinkedListNode; } return reInt; } public T GetElementByIndex(int index) { if (index < 0 || index >= this.Count) { throw new Exception("索引值非法,无法得对象."); } DoubleLinkedListNode<T> reNode = this._headDoubleLinkedListNode; int i = 0; while (reNode != null) { if (i == index) { break; } reNode = reNode.NextDoubleLinkedListNode; ++i; } return reNode.DataValue; } public DoubleLinkedListNode<T> GetNodeByIndex(int index) { if (index < 0 || index >= this.Count) { throw new Exception("索引值非法,无法得对象节点."); } DoubleLinkedListNode<T> reNode = this._headDoubleLinkedListNode; int i = 0; while (reNode != null) { if (i == index) { break; } reNode = reNode.NextDoubleLinkedListNode; ++i; } return reNode; } /// <summary> /// 清除链表中的数据 /// </summary> public void Clear() { this._headDoubleLinkedListNode = null; this._endDoubleLinkedListNode = null; this.size = 0; } /// <summary> /// 查找是否包含当前元素,true为包含 false为不包含 /// </summary> /// <param name="item"></param> /// <returns></returns> public bool Contains(T item) { if (item == null) { throw new Exception("元素为空,无法检测对象是否存在与链表中."); } bool flag = false; if (this.Count != 0) { DoubleLinkedListNode<T> node = this._headDoubleLinkedListNode; while (node != null) { if (node.DataValue.Equals(item)) { flag = true; break; } node = node.NextDoubleLinkedListNode; } } return flag; } /// <summary> /// 初始化链表添加节点 /// </summary> /// <param name="item"></param> public void Add(T item) { if (item == null) { throw new Exception("元素为空,元法进行添加!"); } //要添加的节点 var addItem = new DoubleLinkedListNode<T>(item); //把新节点添加到链表的表尾 if (this._headDoubleLinkedListNode == null) { //如果没有过行过添加 this._headDoubleLinkedListNode = addItem; //第一次添加时,头尾指针都应是一个对象 this._endDoubleLinkedListNode = this._headDoubleLinkedListNode; } else { //如果链表中不为空 this._endDoubleLinkedListNode.NextDoubleLinkedListNode = addItem; addItem.PrevDoubleLinkedListNode = this._endDoubleLinkedListNode; this._endDoubleLinkedListNode = addItem; } } /// <summary> /// 在给定的索引处插入数据 /// </summary> /// <param name="index">索引</param> /// <param name="t">要插入的数据</param> public void Insert(int index, T t) { var doubleLinkedListNode = new DoubleLinkedListNode<T>(t); //索引过小 if (index < 0) { throw new IndexOutOfRangeException(); } //索引过大 if (index >= this.Count) { throw new IndexOutOfRangeException(); } //如果链表是空的,而且索引大于0 if (this.IsEmpty && index > 0) { throw new IndexOutOfRangeException(); } //如果索引为0,意味着向链表头部添加节点。 if (index == 0) { AddFirst(t); return; } //要插入位置的节点 DoubleLinkedListNode<T> current = this._headDoubleLinkedListNode; int i = 0; while (true) { if (i == index) { break; } i++; current = current.NextDoubleLinkedListNode; } //此处非常重要,特别要注意先后次序 //当前节点的上一个的下一个设置为新节点 current.PrevDoubleLinkedListNode.NextDoubleLinkedListNode = doubleLinkedListNode; //新节点的上一个设置为当前节点的上一个 doubleLinkedListNode.PrevDoubleLinkedListNode = current.PrevDoubleLinkedListNode; //新节点的下一个设置为当前节点 doubleLinkedListNode.NextDoubleLinkedListNode = current; //当前节点的上一个设置为新节点 current.PrevDoubleLinkedListNode = doubleLinkedListNode; //大小加一 this.size++; } /// <summary> /// Copy到Array /// </summary> /// <param name="array"></param> /// <param name="arrayIndex"></param> public void CopyTo(T[] array, int arrayIndex) { if (array == null) { throw new Exception("目标数组不可以为空,无法复制"); } if (arrayIndex < 0 || arrayIndex >= array.Length) { throw new Exception("索引值非法,无法进行复制."); } if ((array.Length - arrayIndex) < this.Count || array.Length < this.Count) { throw new Exception("目标数组容量不够,无法进行复制."); } for (int i = 0; i < this.Count; i++) { T item = this.GetElementByIndex(i); array[arrayIndex] = item; ++arrayIndex; } } /// <summary> /// 彩蛋一枚,研究研究!!!! /// 归并排序,非递归版本 /// 步长为1的一轮过后,相邻的两个链表节点已经有序了 /// 步长为2的一轮过后,前两个和紧挨着的后两个就有序了。 /// 步长为4的一轮过后,前四个和紧挨着的后四个就有序了。 /// 跟数组的差别在于:对于数组来说,长度易得,将数组分成两部分容易,将已经分成两部分的再次拆分也容易。 /// 对于链表来说,长度难得,拆分更难得,因而,将链表划成两部分更难得。 /// 对于链表的处理用以下方式: /// 首先将步长设为1,那么将链表两两分组,这两个节点中的前面一个作为第一个链表,后面的一个作为第二个链表。 /// 将这两个链表进行合并,合并完成的结果必然是个有序的链表,当步长为1的合并进行完成之后,链表中相邻的两个 /// 就排好序了,可是整体上可能还是无序的,那么将步长增加一倍,步长为2,继续进行合并,这个时候,第一个链表中 /// 就存放了两个已经排好序的节点,而第二个链表中也是两个已经排好序的节点,继续对这两个链表进行合并,合并的 /// 结果是4个一组的链表排序好了,这样一直进行下去,总该有个头吧,那是自然,头在何处呢?头就在合并次数这里; /// 如果链表中有10个节点,那么第一次进行合并的时候,分成了5组,也就是进行了5次合并;第二次进行合并的时候, /// 步长为2,分成了3组,合并进行了3次,第三次合并的时候,步长为4,合并进行2次,第四次合并的时候,步长为8 /// 合并只需进行1次就可以结束了。 /// 从单向链表的归并,到双向链表的归并非常简单,补上前向节点和尾节点就够了。 /// </summary> public void MergeSort() { //如果是空链表或只有一个节点的链表 //那么是不需要排序的 if (this.IsEmpty || this.size == 1) { return; } int nstep = 1; //步长 //使劲循环 while (true) { DoubleLinkedListNode<T> first; //第一个链表 DoubleLinkedListNode<T> second; //第二个链表 DoubleLinkedListNode<T> _endDoubleLinkedListNode; //链表尾部 DoubleLinkedListNode<T> temp; //临时节点 int firstSize, secondSize; //第一个链表和第二个链表的大小 //第一个链表从头开始 first = this._headDoubleLinkedListNode; //设置链表尾为null _endDoubleLinkedListNode = null; int mergeCount = 0; //合并次数 //第一个链表不空 while (first != null) { //需要合并的数量加一 mergeCount++; //把第一个链表给第二个链表 second = first; //第一个链表的大小设置为0 firstSize = 0; //根据步长得到第一个链表的长度 //下面这个循环还有个目的是确定第二个链表的起始位置 //firstSize是第一个链表的实际长度,而secondSize长度可能大于实际的长度 for (int i = 0; i < nstep; i++) { firstSize++; second = second.NextDoubleLinkedListNode; if (second == null) { break; } } //让第二个链表的长度为步长 secondSize = nstep; //如果第一个链表的长度大于零,或者第二个链表的长度大于零并且第二个链表不为空 //这个循环是用来合并两个有序链表的 while (firstSize > 0 || (secondSize > 0 && second != null)) { //下面这一大段if的意思是,从first或second中掐出来一个较小的节点 //放入temp这个临时节点中 //如果第一个链表的长度为0 if (firstSize == 0) { //将第二个链表中的第一个节点放入临时节点中 temp = second; //将第二个链表下移一位,让第二个链表的第一个节点独立出来 second = second.NextDoubleLinkedListNode; //第二个链表的长度减一 secondSize--; } //如果第二个链表为空或大小是零 else if (second == null || secondSize == 0) { //那么新链表就是第一个链表 temp = first; //将第一个链表下移一位,让第一个链表的第一个节点独立出来 first = first.NextDoubleLinkedListNode; //第一个链表的长度减一 firstSize--; } //到这里的时候,第一第二链表都不空 //如果第一个链表的第一个节点的数值小于第二个链表的第一个节点的数值 else if (first.DataValue.ToString().CompareTo(second.DataValue) <= 0) { //让新链表是第一个链表的第一个节点 temp = first; //第一个链表下移一位,让第一个链表的第一个节点独立出来 first = first.NextDoubleLinkedListNode; //第一个链表的长度减一 firstSize--; } else //到这里的时候,第一第二链表都不空,而且第二个链表的第一个节点的数值小于第一个链表的第一个节点的数值 { //让新链表是第二个链表 temp = second; //第二个链表下移一位,让第二个链表的第一个节点独立出来 second = second.NextDoubleLinkedListNode; //第二个链表的长度减一 secondSize--; } //将得到的较小的哪个临时节点先放入endNode这个临时链表中 //如果临时链表不是空的,意味着这个节点已经不是两个节点中最小的那个节点了 if (_endDoubleLinkedListNode != null) { //那么将得到的临时节点附加在临时链表的最后 _endDoubleLinkedListNode.NextDoubleLinkedListNode = temp; temp.PrevDoubleLinkedListNode = _endDoubleLinkedListNode; //最后将临时节点作为临时链表 //这一句每轮可能会进行很多次 _endDoubleLinkedListNode = temp; } else { //如果临时链表是空的 //每一轮会为headNode赋一次值 //每轮的第一次会将两个链表中最小的那个节点赋给headNode //最后一轮的时候headNode一定是最小的哪个节点 this._headDoubleLinkedListNode = temp; this._headDoubleLinkedListNode.PrevDoubleLinkedListNode = null; //最后将临时节点作为临时链表 _endDoubleLinkedListNode = temp; } } //将第一个链表设置为第二个链表 //到这里的时候second已经前进了一个步长了 //新的first链表就从second开始 first = second; } //走到这里的时候,以某个步长为步进的合并已经完成了 //下面的工作,要么结束,要么将步长设为原来的两倍 //临时链表的下一个设置为null,表示这是个尾节点 //每一轮结束的时候,endNode中放置的是两个链表中最后一个节点 //因为这是最后一个节点,所以就没有下一个了,因而将Next设置为null //如果不设置为null的话,那么链表有可能构成循环链表。 _endDoubleLinkedListNode.NextDoubleLinkedListNode = null; this._endDoubleLinkedListNode = _endDoubleLinkedListNode; //如果要合并的节点数量小于等于1,就直接返回,表明排序完成了 if (mergeCount <= 1) { return; } //否则步长加倍,继续排序 nstep = nstep*2; } } }
双向循环链表(DoubleCircularLinkList.cs)
public class DoubleCircularLinkedList<T> : IEnumerable<T> { private DoubleLinkedListNode<T> _headNode; private DoubleLinkedListNode<T> _nextNode; private DoubleLinkedListNode<T> current; private int currentIndex; public DoubleLinkedListNode<T> HeadNode { get; set; } public DoubleLinkedListNode<T> NextNode { get; set; } public int Count { get; private set; } /// <summary> /// 根据索引获取链表中的节点 /// </summary> /// <param name="index">整型索引</param> /// <returns>节点</returns> public DoubleLinkedListNode<T> this[int index] { get { if (index < 0 || index >= this.Count) { throw new Exception("索引值非法,无法得对象节点."); } DoubleLinkedListNode<T> reNode = this._headNode; int i = 0; while (reNode != null) { if (i == index) { break; } reNode = reNode.NextDoubleLinkedListNode; ++i; } return reNode; } } /// <summary> /// 判断链表是否是空的 /// </summary> public bool IsEmpty { get { return this._headNode == null; } } public void AddAfter(DoubleLinkedListNode<T> node, DoubleLinkedListNode<T> newNode) { this.AddAfter(node, newNode.DataValue); } public void AddAfter(DoubleLinkedListNode<T> node, T t) { if (node == null || t == null) { throw new Exception("元素为空,不可以进行插入"); } int index = this.IndexOf(node.DataValue); if (index != -1) { DoubleLinkedListNode<T> currNode = this.GetNodeByIndex(index); DoubleLinkedListNode<T> upNode = currNode.PrevDoubleLinkedListNode; DoubleLinkedListNode<T> nextNode = currNode.NextDoubleLinkedListNode; var newNode = new DoubleLinkedListNode<T>(t); if (index == 0) { this._headNode.NextDoubleLinkedListNode = newNode; newNode.PrevDoubleLinkedListNode = this._headNode; newNode.NextDoubleLinkedListNode = nextNode; } else if (index == this.Count - 1) { newNode.PrevDoubleLinkedListNode = this._nextNode; this._nextNode.NextDoubleLinkedListNode = newNode; this._nextNode = newNode; } else { nextNode.PrevDoubleLinkedListNode = newNode; currNode.NextDoubleLinkedListNode = newNode; newNode.PrevDoubleLinkedListNode = currNode; newNode.NextDoubleLinkedListNode = nextNode; } } } public void AddBefore(DoubleLinkedListNode<T> node, DoubleLinkedListNode<T> newNode) { this.AddBefore(node, newNode.DataValue); } public void AddBefore(DoubleLinkedListNode<T> node, T t) { if (node == null || t == null) { throw new Exception("元素为空,不可以进行插入"); } int index = this.IndexOf(node.DataValue); if (index != -1) { DoubleLinkedListNode<T> currNode = this.GetNodeByIndex(index); DoubleLinkedListNode<T> upNode = currNode.PrevDoubleLinkedListNode; DoubleLinkedListNode<T> nextNode = currNode.NextDoubleLinkedListNode; var newNode = new DoubleLinkedListNode<T>(t); if (index == 0) { this._headNode.PrevDoubleLinkedListNode = newNode; newNode.NextDoubleLinkedListNode = this._headNode; this._headNode = newNode; } else if (index == this.Count - 1) { upNode.NextDoubleLinkedListNode = newNode; newNode.NextDoubleLinkedListNode = this._nextNode; this._nextNode.PrevDoubleLinkedListNode = newNode; } else { upNode.NextDoubleLinkedListNode = newNode; nextNode.PrevDoubleLinkedListNode = newNode; currNode.PrevDoubleLinkedListNode = upNode; currNode.NextDoubleLinkedListNode = nextNode; } } } /// <summary> /// 添加节点到链表的开头 /// </summary> /// <param name="t"></param> public DoubleLinkedListNode<T> AddFirst(T value) { var doubleLinkedListNode = new DoubleLinkedListNode<T>(value); //如果头为null if (this._headNode == null) { //把头节点设置为node this._headNode = doubleLinkedListNode; //因为是空链表,所以头尾一致 this._headNode = doubleLinkedListNode; //大小加一 this.Count ++; return null; } //原来头节点的上一个为新节点 this._headNode.PrevDoubleLinkedListNode = doubleLinkedListNode; //新节点的下一个为原来的头节点 doubleLinkedListNode.NextDoubleLinkedListNode = this._headNode; //新头节点为新节点 this._headNode = doubleLinkedListNode; //大小加一 this.Count++; return this._headNode; } public void AddFirst(DoubleLinkedListNode<T> node) { this.AddFirst(node.DataValue); } /// <summary> /// 添加节点到链表的末尾 /// </summary> /// <param name="t">要添加的数据</param> public DoubleLinkedListNode<T> AddLast(T t) { var doubleLinkedListNode = new DoubleLinkedListNode<T>(t); //当前Node this.current = doubleLinkedListNode; //如果头为null Count =0 if (this._headNode == null) { //把头节点设置为当前node this._headNode = this.current; //循环双向链表头尾相连 前驱和后继都为当前node this._headNode.PrevDoubleLinkedListNode = this.current; this._headNode.NextDoubleLinkedListNode = this.current; //因为是空链表,所以头尾一致 //大小加一 this.Count++; return this.current; } //只包含一个头结点 Count=1 if (this.Count == 1) { for (int index = 0; index < this.Count; index++) { //判定检索原有链表中的尾节点 尾节点必定指向首节点 if (this[index].NextDoubleLinkedListNode == this._headNode) { //原尾节点的后置指向当前插入节点 this[index].NextDoubleLinkedListNode = this.current; this[index].PrevDoubleLinkedListNode = this.current; this.current.PrevDoubleLinkedListNode = this[index]; this.current.NextDoubleLinkedListNode = this[index]; this.Count++; return this.current; } } } //两个节点以上 Count>=2 if (this.Count >= 2) { for (int index = 0; index < this.Count; index++) { //判定检索原有链表中的尾节点 尾节点必定指向首节点 if (this[index].NextDoubleLinkedListNode == this._headNode) { //原尾节点的后置指向当前插入节点 this._headNode.PrevDoubleLinkedListNode = this.current; this[index].NextDoubleLinkedListNode = this.current; this.current.PrevDoubleLinkedListNode = this[index]; this.current.NextDoubleLinkedListNode = this._headNode; this.Count++; return this.current; } } } return this.current; } public void AddLast(DoubleLinkedListNode<T> node) { this.AddLast(node.DataValue); } /// <summary> /// 移除链表中的节点 /// </summary> /// <param name="index">要移除的节点的索引</param> public bool Remove(DoubleLinkedListNode<T> node) { if (node == null) { throw new Exception("节点不可以为空,无法进行删除"); } int index = this.IndexOf(node.DataValue); return this.Remove(index); } public bool Remove(int index) { if (index < 0 || index >= this.Count) { throw new Exception("索引值非法,无法进行删除。"); } bool flag = false; DoubleLinkedListNode<T> node = this._headNode; int i = 0; while (node != null) { if (i == index) { DoubleLinkedListNode<T> upNode = node.PrevDoubleLinkedListNode; DoubleLinkedListNode<T> nextNode = node.NextDoubleLinkedListNode; if (index == 0) { this._headNode = node.NextDoubleLinkedListNode; node = null; } else if (index == this.Count - 1) { this._nextNode = upNode; this._nextNode.NextDoubleLinkedListNode = null; node = null; } else { upNode.NextDoubleLinkedListNode = nextNode; nextNode.PrevDoubleLinkedListNode = upNode; node = null; } flag = true; break; } node = node.NextDoubleLinkedListNode; ++i; } return flag; } /// <summary> /// 移除头节点 /// </summary> public void RemoveHeadNode() { //链表头节点是空的 if (this.IsEmpty) { throw new Exception("链表是空的。"); } //如果size为1,那就是清空链表。 if (this.Count == 1) { this.Clear(); return; } //将头节点设为原头结点的下一个节点,就是下一个节点上移 this._headNode = this._headNode.NextDoubleLinkedListNode; //处理上一步遗留问题,原来的第二个节点的上一个是头结点,现在第二个要变成头节点,那要把它的Prev设为null才能成为头节点 this._headNode.PrevDoubleLinkedListNode = null; //大小减一 this.Count--; } /// <summary> /// 移除尾节点 /// </summary> public void RemoveEndNode() { //链表头节点是空的 if (this.IsEmpty) { throw new Exception("链表是空的。"); } //如果size为1,那就是清空链表。 if (this.Count == 1) { this.Clear(); return; } //尾节点设置为倒数第二个节点 this._nextNode = this._headNode.PrevDoubleLinkedListNode; //将新尾节点的Next设为null,表示它是新的尾节点 this._headNode.NextDoubleLinkedListNode = null; //大小减一 this.Count--; } public DoubleLinkedListNode<T> Find(T value) { throw new NotImplementedException(); } public DoubleLinkedListNode<T> FindLast(T value) { throw new NotImplementedException(); } public int IndexOf(T item) { if (item == null || this.Count == 0 || this._headNode == null) { throw new Exception("无法得到元素索引"); } int reInt = -1; int i = 0; DoubleLinkedListNode<T> node = this._headNode; while (node != null) { if (node.DataValue.Equals(item)) { reInt = i; break; } ++i; node = node.NextDoubleLinkedListNode; } return reInt; } public T GetElementByIndex(int index) { if (index < 0 || index >= this.Count) { throw new Exception("索引值非法,无法得对象."); } DoubleLinkedListNode<T> reNode = this._headNode; int i = 0; while (reNode != null) { if (i == index) { break; } reNode = reNode.NextDoubleLinkedListNode; ++i; } return reNode.DataValue; } public DoubleLinkedListNode<T> GetNodeByIndex(int index) { if (index < 0 || index >= this.Count) { throw new Exception("索引值非法,无法得对象节点."); } DoubleLinkedListNode<T> reNode = this._headNode; int i = 0; while (reNode != null) { if (i == index) { break; } reNode = reNode.NextDoubleLinkedListNode; ++i; } return reNode; } /// <summary> /// 清除链表 /// </summary> public void Clear() { this.Count = 0; this.HeadNode = null; this.NextNode = null; } private void Reset() { this.currentIndex = 0; this.current = this.HeadNode; } public void ShowtheLinkList() { var p = new DoubleLinkedListNode<T>(); p = this._headNode; int index = 0; int index2 = 0; while (p != null) { string prev = " "; string data = " "; string next = " "; if (p.PrevDoubleLinkedListNode == null) { prev = "null"; } else { prev = Convert.ToString((p.PrevDoubleLinkedListNode.DataValue as PersonModel).id); } if (p.DataValue == null) { data = "null"; } else { data = Convert.ToString((p.DataValue as PersonModel).id); } if (p.NextDoubleLinkedListNode == null) { next = "null"; } else { next = Convert.ToString((p.NextDoubleLinkedListNode.DataValue as PersonModel).id); } Console.Write("前驱为:{0},数据为:{1},后继为:{2},索引为:{3}\n", prev, data, next, index); p = p.NextDoubleLinkedListNode; if (index == this.Count - 1) { Console.Write("一个轮回"); Console.ReadKey(); } ++index; } } #region IEnumerable<T> 成员 public IEnumerator<T> GetEnumerator() { DoubleLinkedListNode<T> currNode = this._headNode; while (currNode != null) { yield return currNode.DataValue; currNode = currNode.NextDoubleLinkedListNode; } } #endregion #region IEnumerable 成员 IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); } #endregion }
未完待续后续将进入栈和队列,卧槽...脖子疼
相关文章推荐
- c#+dev-GridControl的简单用法
- C#之WinForm基础 画出一条直线
- 总结C#动态调用WCF接口的两种方法
- 解决C#中Linq GroupBy 和OrderBy失效的方法
- C#直接使用DllImport外部Dll的方法
- C# 调用BarTender模板 打印
- C# 数字大写转换
- C# 获取字符串的字节数
- C# 选择文件夹,遍历文件夹,复制图片并改名,读写XML
- C# 错误日期格式转正确日期格式
- C# Enum,Int,String的互相转换
- C# NPOI excel操作封装
- 自学DevExpress为Form表格换肤
- 【c#】关于设置RichTextBox背景透明+无光标只读状态
- C#组件系列 你值得拥有的一款Excel处理神器Spire.XLS
- C# 生成缩略图
- C# 子窗体在父窗中间
- C# 带参访问接口,WebClient方式
- C# winform中一个类中如何调用另一个窗体的控件或方法
- C#基础总结