zoukankan      html  css  js  c++  java
  • 链表

    链表

    前言:LinkedList<T>是一个双向链表,其元素指向他前面和后面的元素。如下图所示,这样一来,通过移动到下一个元素可以正向的遍历整个链表。通过移动到前一个元素可以反向遍历整个链表。

    链表的优点:如果将元素插入列表的中间位置,使用链表就会非常快。在插入一个元素时,只需要修改上一个元素的Next引用和下一个元素的Previous引用,使他们引用所插入的元素。在List<T>类中,插入一个元素时,需要移动该元素后面的所有的元素。

    链表的缺点:链表的元素只能一个接一个的访问。这需要较长的时间来查找位于链表中间或者尾部的元素。

    链表不能在列表中仅存储元素。存储元素时,链表还必须促成农户每个元素的下一个元素和上一个元素的信息。这就是LinkedList<T>包含LinkedListNode<T>类型的元素的原因。使用LinkedListNode<T>类 ,可以获得列表中的下一个元素和上一个元素。LinkedListNode<T>定义了属性List、Next、Previous、和Value。List属性返回与节点相关的ListedList<T>对象,Next和Previous属性用于遍历链表。访问当前节点之后和之前的节点。Value返回与节点相关的元素,其类型是T。

    LinkedList<T>类定义的成员可以访问链表中的第一个和最后一个元素(First和Last)、在指定的位置上插入元素(AddAfter()、AddBefore()、AddFirst()、AddLast()方法)删除指定位置的元素(Remove()、RemoveFirst()、RemoveLast())、从链表的开头(Find()方法)或者结尾(FindLast()方法)开始搜索元素。

    我们实例的应用程序使用了一个链表和一个列表。链表包含文档,这与上一个队列例子相同,但文档有 一个额外的优先级。在链表中,文档按照优先级来排序。如果多个文档的优先级相同,这些元素就按照文档的插入的时间来排序。

    在链表中添加新文档时,他们应放在优先级相同的最后一个文档的后面。集合LinkedList<Document>包含LinkedListNode<Document>类型的元素。LinkedListNode<T>类添加了Next和Previous属性。使搜索过程中能从一个节点移动到下一个节点上。要引用这些元素,应把List<T>定义为List<LinkedListNode<Document>>。

    在上面的例子中,Document类扩展为包含优先级。优先级用类的构造函数设置:

     

        /// <summary>
        /// 文档类
        /// </summary>
        public class Document
        {
    
            public string Title { get; set; }               //标题
            public string Content { get; set; }             //内容
            public byte Priority { get; set; }              //优先级
    
            /// <summary>
            /// 构造函数的初始化赋值
            /// </summary>
            /// <param name="title"></param>
            /// <param name="content"></param>
            /// <param name="priority"></param>
            public Document(string title, string content, byte priority)
            {
                this.Title = title;
                this.Content = content;
                this.Priority = priority;
            }
    
        }

     解决方案的核心是PriorityDocumentManager类。这个类很容易使用。在这个类的公共接口中,可以把新的Document元素添加到链表中,可以检索第一个文档。为了便于测试,它还提供了一个方法,在元素链接到链表中,该方法可以显示集合中的所有的元素。

    PriorityDocumentManage类包含两个集合。LinkedList<Document>类型的集合包含所有的文档。List<LinkedListNode<Document>>类型的集合包含最多10个元素的引用。它们是添加指定优先级的新文档的入口点。这两个集合变量都用PriorityDocumentManager类的构造函数来进行实例化。列表集合也用null初始化。

     

        /// <summary>
        /// 优先级文档管理器
        /// </summary>
        public class PriorityDocumentManager
        {
    
            private readonly LinkedList<Document> _documentList;                    //双向链接列表集合
            private readonly List<LinkedListNode<Document>> _priorityNodes;         //优先级节点              
    
            /// <summary>
            /// 构造函数初始化
            /// </summary>
            public PriorityDocumentManager()
            {
                _documentList = new LinkedList<Document>();
                _priorityNodes = new List<LinkedListNode<Document>>(10);
                for (int i = 0; i < 10; i++)
                {
                    //添加空的节点
                    _priorityNodes.Add(new LinkedListNode<Document>(null));
                }
            }
    
            /// <summary>
            /// 添加文档
            /// </summary>
            /// <param name="d"></param>
            public void AddDocument(Document d)
            {
                if (d == null)
                    throw new ArgumentException("d");
                AddDocumentToPriorityNode(d, d.Priority);
            }
    
            /// <summary>
            /// 显示增加的节点
            /// </summary>
            public void DisplayAddNodes()
            {
                foreach (var doc in _documentList)
                {
                    Console.WriteLine("优先级:{0},title:{1}", doc.Priority, doc.Title);
                }
            }
    
            /// <summary>
            /// 从链表中返回第一个文档(优先级最高的文档),并从链表中删除它.
            /// </summary>
            /// <returns></returns>
            public Document GetDocument()
            {
                Document doc = _documentList.First.Value;
                return doc;
            }
    
            /// <summary>
            /// 将文档添加到优先节点
            /// </summary>
            /// <param name="doc">文档对象</param>
            /// <param name="priority">优先级</param>
            private void AddDocumentToPriorityNode(Document doc, int priority)
            {
                if (priority > 9 || priority < 0)
                {
                    throw new AggregateException("优先级必须是0到9之间的数字");
                }
    
                //获取节点中包含的值,如果是空的话
                if (_priorityNodes[priority].Value == null)
                {
                    //递减优先级
                    --priority;
                    //如果优先级大于零的话 递归检查
                    if (priority >= 0)
                    {
                        //检查下一个较低的优先级
                        AddDocumentToPriorityNode(doc, priority);
                    }
                    //现在没有优先级或者更低的优先级 将新文档添加到末尾
                    else
                    {
                        //在结尾处添加新节点
                        _documentList.AddLast(doc);
                        //将最后一个节点赋给优先级节点
                        _priorityNodes[doc.Priority] = _documentList.Last;
                    }
                }
    
                //一个优先级节点存在
                else
                {
                    //得到节点:当执行到第三个的值的时候,首先拿到上一个值的节点的值
                    LinkedListNode<Document> prioNode = _priorityNodes[priority];
                    //如果具有相同的优先级节点
                    if (priority == doc.Priority)
                    {
                        //在指定的现有节点后添加包含指定值得新节点
                        _documentList.AddAfter(prioNode, doc);
                        //将优先级节点设置为具有相同优先级的最后一个节点
                        _priorityNodes[doc.Priority] = prioNode.Next;
                    }
                    //只有具有较低优先级的优先级节点存在
                    else
                    {
                        //获得较低优先级的第一个节点
                        LinkedListNode<Document> firstPrioNode = prioNode;
                        while (firstPrioNode.Previous != null && firstPrioNode.Previous.Value.Priority == prioNode.Value.Priority)
                        {
                            firstPrioNode = prioNode.Previous;
                            prioNode = firstPrioNode;
                        }
                        //在指定的现有的节点前添加新值
                        _documentList.AddBefore(firstPrioNode, doc);
                        //将优先值节点设置为新值
                        _priorityNodes[doc.Priority] = firstPrioNode.Previous;
                    }
                }
            }
    
        }

     


    在Main方法中,PriorityDocumentManager类用于说明其功能。在链表中添加8个优先级不同的新文档。在显示整个链表。

            static void Main(string[] args)
            {
    
                var pmd = new PriorityDocumentManager();
                pmd.AddDocument(new Document("one", "Sample", 8));
                pmd.AddDocument(new Document("four", "Sample", 8));
                pmd.AddDocument(new Document("two", "Sample", 3));
                pmd.AddDocument(new Document("three", "Sample", 4));
                pmd.AddDocument(new Document("five", "Sample", 1));
                pmd.AddDocument(new Document("six", "Sample", 9));
                pmd.AddDocument(new Document("seven", "Sample", 1));
                pmd.AddDocument(new Document("eight", "Sample", 1));
                pmd.DisplayAddNodes();
                Console.ReadKey();
    
            }


    在处理好的结果中,文档先按优先级排序,在按文档添加文档的时间排序。

      

      

  • 相关阅读:
    J2EE系列 (一) 几个技术规范
    MyEclipse 10 优化技巧
    J2EE (二) Servlet设置Session Cookies
    CSS 外层box自动计算高度的问题
    UI设计技巧Div封闭式Div导致页面显示异常
    Windows 7 IIS7 无法启动, 显示WAS & W3SVC没有启动的错误提示
    Windows 7 截图
    GridView技巧增加序号列
    ERWin & ERStudio图里的实线和虚线的含义
    [转]CSS布局口诀 CSS BUG顺口溜
  • 原文地址:https://www.cnblogs.com/MoRanQianXiao/p/7838507.html
Copyright © 2011-2022 走看看