• 数据结构之基于无序链表的集合和映射


    使用代码实现自定义的集合类

       #region 链表类
        public class MyLinkedList<T>
        {
            //当前链表类记录这个链表的头部类
            private Node head;
            //链表的节点数量
            private int N;
            public MyLinkedList()
            {
                N = 0;
                //因为一开始链表没有元素,所以头部节点指向空。
                head = null;
            }
    
    
    
            /// <summary>
            /// 链表节点数量
            /// </summary>
            public int Count
            {
                get { return N; }
            }
            /// <summary>
            /// 链表是否为空
            /// </summary>
            public bool IsEmpty
            {
                get { return N == 0; }
            }
    
            public void Add(int index, T e)
            {
                if (index < 0 || index > N)
                {
                    throw new Exception("非法索引");
                }
    
                if (index == 0)
                {
                    //新的头部节点
                    //1:添加新节点
                    //Node node = new Node(e);
                    ////2:将新添加的头结点的箭头指向原先头结点
                    //node.next = head;
                    ////3:现在的头结点信息赋给类的头结点字段,记录下来。
                    //head = node;
                    //其实上面三步可以结合到一步中,
                    head = new Node(e, head);
                }
                else
                {
                    //添加非头部节点
                    //1.需要找到插入位置的上一个节点,对于链表来说就要从头部节点开始一步一步的查找了
                    Node pre = head;
                    //一步一步遍历找到前一个节点信息
                    for (int i = 0; i < index - 1; i++)
                    {
                        pre = pre.next;
                    }
                    //1:将前一节点的下一节点信息赋值给当前节点对象的下一节点字段,目的是为了让当前节点能够链接到下一节点
                    Node node = new Node(e);
                    node.next = pre.next;
                    //2:前一节点链接到新插入的节点 此时链表已经重新完成
                    pre.next = node;
                    //上面代码也可以合成一句
                    //   pre.next = new Node(e, pre.next);
    
                }
                //链表的元素加一
                N++;
            }
    
            public void AddFirst(T e)
            {
                Add(0, e);
            }
    
            public void AddLast(T e)
            {
                Add(N, e);
            }
    
            /// <summary>
            /// 节点类  不让外部知道此类,设为私有
            /// </summary>
            private class Node
            {
                //当前节点
                public T e;
                //当前节点的下一节点
                public Node next;
                public Node(T e, Node next)
                {
                    this.e = e;
                    this.next = next;
                }
                public Node(T e)
                {
                    this.e = e;
                }
    
            }
    
    
            public T Get(int index)
            {
                if (index < 0 || index >= N)
                {
                    throw new Exception("非法索引");
                }
    
                Node currentNode = head;//从头结点开始查找
                for (int i = 0; i < index; i++)
                {
                    currentNode = currentNode.next;
                }
    
                return currentNode.e;
            }
    
    
            public T GetFirst()
            {
                return Get(0);
            }
            public T GetLast()
            {
                return Get(N - 1);
            }
    
            /// <summary>
            /// 修改
            /// </summary>
            /// <param name="index"></param>
            /// <param name="e"></param>
            /// <returns></returns>
            public void Set(int index, T e)
            {
                if (index < 0 || index >= N)
                {
                    throw new Exception("非法索引");
                }
    
                Node currentNode = head;//从头结点开始查找
                for (int i = 0; i < index; i++)
                {
                    currentNode = currentNode.next;
                }
    
                currentNode.e = e; ;
            }
            /// <summary>
            /// 查找链表中是否存在此元素
            /// </summary>
            /// <param name="e"></param>
            /// <returns></returns>
            public bool Contains(T e)
            {
                Node current = head;
                while (current != null)
                {
                    if (current.e.Equals(e))
                    {
                        return true;
                    }
    
                    current = current.next;
                }
    
                return false;
            }
            /// <summary>
            /// 可以重写tostring打印方法
            /// 打印出链表信息
            /// </summary>
            /// <returns></returns>
            public override string ToString()
            {
                StringBuilder stringBuilder = new StringBuilder();
                Node cur = head;
                while (cur != null)
                {
                    stringBuilder.Append(cur.e + "->");
                    cur = cur.next;
                }
                stringBuilder.Append("null");
                return stringBuilder.ToString();
    
            }
    
            #region 删除节点
    
            public T Remove(int index)
            {
                if (index < 0 || index > N)
                {
                    throw new Exception("非法索引");
                }
    
                if (index == 0)
                {
                    Node delNode = head;
                    //直接将原头部节点指向的下一节点的信息存储到头部节点的字段上,直接这样就能删除原头部节点了
                    head = delNode.next;
                    N--;
                    return delNode.e;
                }
                else
                {
                    Node pre = head;
                    //找到删除节点的前一节点信息
                    for (int i = 0; i < index - 1; i++)
                    {
                        pre = pre.next;
                    }
                    Node delNode = pre.next;
                    //1:z将前一节点的指向做更改
                    pre.next = delNode.next;
                    N--;
                    return delNode.e;
                }
            }
    
            public T RemoveFirst()
            {
                return Remove(N);
            }
    
            #endregion
            #region 删除节点  根据值节点查找
    
            public void Remove(T e)
            {
                if (head == null)
                {
                    return;
                }
    
                if (head.e.Equals(e))
                {
                    //删除的是头结点
                    head = head.next;
                    N--;
                }
                else
                {
                    Node current = head;
                    Node pre = null;
                    while (current != null)
                    {
                        if (current.e.Equals(e))
                        {
                            break;
                        }
    
                        pre = current;
                        current = current.next;
    
                    }
    
                    if (current != null)
                    {
                        pre.next = current.next.next;
                        N--;
                    }
                }
    
            }
    
            #endregion
        }
        #endregion
    View Code
        interface ISet<E>
        {
            int Count { get; }
            bool IsEmpty { get; }
            void Add(E e);
            void Remove(E e);
            bool Contains(E e);
    
        }
    View Code
      class LinkedListISet<E> : ISet<E>
        {
            private MyLinkedList<E> list;
            public LinkedListISet()
            {
                list = new MyLinkedList<E>();
            }
    
    
    
            public int Count { get { return list.Count} }
            public bool IsEmpty { get { return list.IsEmpty } }
            /// <summary>
            /// 基于无序链表的集合的添加方法
            /// </summary>
            /// <param name="e"></param>
            public void Add(E e)
            {
                if (!list.Contains(e))
                {
                    list.AddFirst(e);
                }
            }
    
            public bool Contains(E e)
            {
                return list.Contains(e);
            }
    
            public void Remove(E e)
            {
                list.Remove(e);
            }
        }
    View Code

    测试代码:

    class Program
        {
            static void Main(string[] args)
            { 
                //假设words包含了很多单词
                List<string> words = new List<string>();
                LinkedListISet<string> linkedListISet = new LinkedListISet<string>();
                foreach (var item in words)
                {
                    linkedListISet.Add(item); 
                } 
    
               Console.WriteLine(); 
            }
    
        }
    View Code

    从上面代码能看出来这个性能是很慢的,因为每次添加的时候都要看一下这个单词是否已经包含了,每次看是否包含的时候都要从链表的头到尾遍历一次。可以使用映射解决问题。

    下面创建一个自定义的字典类:

        
    
       interface IDictionary<Key, Value>
        {
            int Count { get; }
            bool IsEmpty { get; }
            void Add(Key key, Value value);
            void Remove(Key key);
            bool ContainsKey(Key key);
            Value Get(Key key);
            void Set(Key key, Value value);
    
        }
    
    
    
    
    
    
    
    /// <summary>
        /// 具有键值的链表类
        /// </summary>
        /// <typeparam name="Key"></typeparam>
        /// <typeparam name="Value"></typeparam>
        class LinkedListKeyValue<Key, Value>
        {
            /// <summary>
            /// 节点
            /// </summary>
            private class Node
            {
                public Key key;
                public Value value;
                public Node next;
                public Node(Key key, Value value, Node next)
                {
                    this.key = key;
                    this.value = value;
                    this.next = next;
                }
                /// <summary>
                /// 重写输出
                /// </summary>
                /// <returns></returns>
                public override string ToString()
                {
                    return key.ToString() + ":" + value.ToString();
                }
    
            }
    
            private Node head;
            public int N;
            public LinkedListKeyValue()
            {
                head = null;
                N = 0;
            }
    
            public int Count { get { return N; } }
            public bool IsEmpty { get { return N == 0; } }
            /// <summary>
            /// 
            /// </summary>
            /// <param name="key"></param>
            /// <returns></returns>
            private Node GetNode(Key key)
            {
                Node cur = head;
                while (cur != null)
                {
                    if (cur.key.Equals(key))
                        return cur;
    
                    cur = cur.next;
                }
    
                return null;
            }
    
            public void Add(Key key, Value value)
            {
                Node node = GetNode(key);
                if (node == null)
                {
                    head = new Node(key, value, head);
                }
    
            }
    
            public bool Contains(Key key)
            {
                return GetNode(key) != null;
            }
    
            public Value Get(Key key)
            {
                Node node = GetNode(key);
                if (node == null)
                {
                    throw new ArgumentException($"键{key}不存在");
                }
                else
                {
                    return node.value;
                }
    
            }
    
            public void Set(Key key, Value value)
            {
                Node node = GetNode(key);
                if (node == null)
                    throw new Exception();
                node.value = value;
            }
            public void Remove(Key key)
            {
                if (head == null)
                {
                    return;
                }
    
                if (head.key.Equals(key))
                {
                    //删除的是头结点
                    head = head.next;
                    N--;
                }
                else
                {
                    Node current = head;
                    Node pre = null;
                    while (current != null)
                    {
                        if (current.key.Equals(key))
                        {
                            break;
                        }
    
                        pre = current;
                        current = current.next;
    
                    }
    
                    if (current != null)
                    {
                        pre.next = current.next.next;
                        N--;
                    }
                }
    
            }
    
        }
    
    
        /// <summary>
        /// 实现自定义的字典类
        /// </summary>
        /// <typeparam name="Key"></typeparam>
        /// <typeparam name="Value"></typeparam>
        public class LinkedListDictionary<Key, Value> : IDictionary<Key, Value>
        {
    
            private LinkedListKeyValue<Key, Value> list;
            public LinkedListDictionary()
            {
                list = new LinkedListKeyValue<Key, Value>();
            }
    
            public int Count { get { return list.Count; } }
    
            public bool IsEmpty { get { return list.IsEmpty; } }
    
            public void Add(Key key, Value value)
            {
                list.Add(key, value);
            }
    
            public bool ContainsKey(Key key)
            {
                return list.Contains(key);
            }
    
            public Value Get(Key key)
            {
                return list.Get(key);
            }
    
            public void Remove(Key key)
            {
                list.Remove(key);
            }
    
            public void Set(Key key, Value value)
            {
                list.Set(key, value);
            }
        }
    View Code

    但是就算是这样性能还是很慢的,所以我们可以使用基于有序数组的集合和映射来解决这个问题,有时间再深入,简单来说就是查找元素这块是用二分查找算法实现的,所以比基于无序链表的集合和映射在查找元素方法上性能更强。

  • 相关阅读:
    设置跨域
    Vs自定nuget push菜单
    VS IIS Express 支持局域网访问
    字符串GZIP压缩解压
    C# 使用 protobuf 进行对象序列化与反序列化
    RabbitMQ
    如果调用.net core Web API不能发送PUT/DELETE请求怎么办?
    log4net配置使用
    redis实现消息队列
    Error-the resource is not on the build path of a java project
  • 原文地址:https://www.cnblogs.com/anjingdian/p/15192301.html
Copyright © 2020-2023  润新知