线性表之链表

来源:互联网 发布:手机网络慢怎么解决 编辑:程序博客网 时间:2024/06/05 04:57
1,为什么要使用链表
通过上一篇的学习,我们知道顺序表存在一些问题,主要有以下两个方面。
1,顺序表的长度是固定的,如果超出分配的长度就会造成溢出,如果存放的数据太少则会造成空间浪费。
2,在插入元素和删除元素时(尤其不在尾部时),会移动大量的元素,造成性能和效率低下。
基于以上问题,使用链表可以很好地避免顺序表中出现的问题。这也是我们要使用链表的原因。

2,链表的存储结构:


    从上图可以看出,单链表中的每个结点都包含一个“数据域”和一个“指针域”。“数据域”中包含当前结点的数据,“指针域”包含下一节点的存储地址,头指针head是指向开始结点的,结束结点没有后继结点,所以结束结点的指针域为空,即null。

3,链表的常用操作及实现代码
链表常用的操作有:
1,插入结点到表头
思路:将head头指针的next指针给新增结点的next,然后将整个新增结点给head头指针的next。因此时间复杂度为O(1)。
示意图:


2,插入结点到表尾
思路:插入方法与插入到表头一样,只不过多一个步骤就是通过head头指针循环找到终端结点。因此时间复杂度为O(n)。
示意图:


3,插入结点(1≤i≤ListLength(L))
思路:插入方法与插入到表头一样,多循环查找当前结点的动作。因此时间复杂度为O(n)。
示意图:


4,删除结点
思路:同插入结点一样,时间复杂度为O(n)。
示意图:


5,查找结点
思路:与插入结点和删除结点方法类似,时间复杂度为O(n)。
6,获取链表长度
思路:不像顺序表是连续存储的,获取表的长度非常容易。在链表中,数据不是连续存储的,因此需要循环遍历才能求得链表的长度,所以时间复杂度为O(n)。

namespace DS.BLL{    /// <summary>    /// 封装链表的常用操作    /// </summary>    public class ChainListBLL    {        /// <summary>        /// 插入结点在表头        /// </summary>        /// <typeparam name="T"></typeparam>        /// <param name="head"></param>        /// <param name="data"></param>        /// <returns></returns>        public static Node<T> InsertFirst<T>(Node<T> head, T data)        {            //创建一个新结点            Node<T> node = new Node<T>();            node.data = data;            node.next = head;            head = node;            return head;        }        /// <summary>        /// 插入结点在表尾        /// </summary>        /// <typeparam name="T"></typeparam>        /// <param name="head"></param>        /// <param name="data"></param>        /// <returns></returns>        public static Node<T> InsertEnd<T>(Node<T> head, T data)        {            //创建一个新结点            Node<T> node = new Node<T>();            node.data = data;            node.next = null;            //空链表直接返回新增的结点            if (head == null)            {                head = node;                return head;            }            GetLastNode(head).next = node;            return head;        }        /// <summary>        /// 插入结点(在包含关键字key的结点之后插入新的结点)        /// </summary>        /// <typeparam name="T"></typeparam>        /// <param name="head"></param>        /// <param name="data"></param>        /// <returns></returns>        public static Node<T> Insert<T,W>(Node<T> head,string key,Func<T,W> where, T data) where W:IComparable        {             //检查链表是否为空            if (head == null) return null;            //查找包含关键字key的结点            if (where(head.data).CompareTo(key) == 0)            {                Node<T> node = new Node<T>();                node.data = data;                node.next = head.next; //注意这里顺序不要弄反了                head.next = node;            }            Insert(head.next,key,where,data); //用递归继续查找下一个结点            return head;        }        /// <summary>        /// 删除结点(删除包含关键字key的结点)        /// </summary>        /// <typeparam name="T"></typeparam>        /// <typeparam name="W"></typeparam>        /// <param name="head"></param>        /// <param name="key"></param>        /// <param name="where"></param>        /// <returns></returns>        public static Node<T> Delete<T, W>(Node<T> head, string key, Func<T, W> where) where W : IComparable        {            if (head == null) return null;            //如果只有一个结点            if (where(head.data).CompareTo(key) == 0)            {                if (head.next != null) head = head.next; //向后移动指针                else return head = null;            }            else            {                //判断此结点是否是要删除结点的前一结点                while (head.next != null && where(head.next.data).CompareTo(key) == 0)                {                    head.next = head.next.next;                }            }            Delete(head.next,key,where); //使用递归继续查找            return head;        }        /// <summary>        /// 查找结点(查找包含关键字key的结点)        /// </summary>        /// <typeparam name="T"></typeparam>        /// <typeparam name="W"></typeparam>        /// <param name="head"></param>        /// <param name="key"></param>        /// <param name="where"></param>        /// <returns></returns>        public static Node<T> GetNodeByKey<T, W>(Node<T> head, string key, Func<T, W> where) where W : IComparable        {            if (head == null) return null;            if (where(head.data).CompareTo(key) == 0) return head;            return GetNodeByKey(head.next,key,where);        }        /// <summary>        /// 获取链表长度        /// </summary>        /// <typeparam name="T"></typeparam>        /// <param name="head"></param>        /// <returns></returns>        public static int GetLength<T>(Node<T> head)        {            int count = 0;            while (head != null)            {                head = head.next; //移动指针                count++;            }            return count;        }        private static Node<T> GetLastNode<T>(Node<T> head)        {            if (head.next == null) return head; //最后结点            return GetLastNode(head.next); //使用递归继续查找        }            }    /// <summary>    /// 封装链表    /// </summary>    /// <typeparam name="T"></typeparam>    public class Node<T>    {        public T data; //数据        public Node<T> next; //指针    }}

0 0
原创粉丝点击