zoukankan      html  css  js  c++  java
  • C#单链表(数据结构)

    学习单链表的源码项目:http://files.cnblogs.com/xmfdsh/CSharp%E5%8D%95%E9%93%BE%E8%A1%A8.rar

    链表是用一组任意的存储单元来存储线性表中的数据元素(在存储单元中可以是连续的,也可以是不连续的)。链表在存储数据元素时,除了存储数据元素本身的信息外,还要存储与它相邻的数据元素的存储地址信息。这两部分信息组成该数据元素的存储映像,称为节点。

    节点的形象图如下:

    首先定义一个类Node来表示这些节点:

    public class Node<T>
        {
            private T data;        //数据域
            private Node<T> next;  //引用域
    
            #region 构造函数
            /// <summary>
            /// 构造函数
            /// </summary>
            /// <param name="val"></param>
            /// <param name="p"></param>
            public Node(T val, Node<T> p)
            {
                data = val;
                next = p;
            }
            public Node(Node<T> p)
            {
                next = p;
            }
            public Node(T val)
            {
                data = val;
                next = null;
            }
            public Node()
            {
                data = default(T);
                next = null;
            } 
            #endregion
            
            //数据域属性
            public T Data
            {
                get
                {
                    return data;
                }
                set
                {
                    data = value;
                }
            }
            //引用域属性
            public Node<T> Next
            {
                get
                {
                    return next;
                }
                set
                {
                    next = value;
                }
            }
        }

    通常,我们把链表化成用箭头相连接的节点序列,节点间的箭头表示引用域中存储的地址。具体单链表的形式表示如下:

    网上找到 图片,把循环列表 和 双向链表都弄上去了,也好提前了解下

    因此要定义一个类表示整个链表,其中中间当然运用到了之前写Node类,类中的属性如下:

           private Node<T> head;//单链表头引用
            //头引用属性
            public Node<T> Head
            {
                get
                {
                    return head;
                }
                set
                {
                    head = value;
                }
            }
            //构造函数
            public LinkList()
            {
                head = null;
            }

    接下来就是实现之前讲的顺序表中定义好的接口 http://www.cnblogs.com/xmfdsh/p/3698456.html

            //求单链表长度
            public int GetLength()
            {
                Node<T> p = head;
                int len = 0;
                while(p!=null)
                {
                    len++;
                    p = p.Next;
                }
                return len;
            }
            //清空单链表
            public void Clear()
            {
                head = null;
            }
    
            public bool IsEmpty()
            {
                if(head==null)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
    
            public bool IsFull()
            {
                throw new NotImplementedException();
            }
            //在单链表末尾添加新元素
            public void Append(T item)
            {
                Node<T> q = new Node<T>(item);
                Node<T> p = new Node<T>();
                if(head==null)
                {
                    head = q;
                    return;
                }
                p = head;
                while(p.Next!=null)
                {
                    p = p.Next;
                }
                p.Next = q;
            }
            //在单链表第i个节点位置插入一个item的节点
            public void Insert(T item, int i)
            {
                if(IsEmpty()||i<1)
                {
                    Console.WriteLine("链表为空或插入位置不允许");
                    return;
                }
                if (i == 1)
                {
                    Node<T> q = new Node<T>(item);
                    q.Next = head;
                    head = q;
                    return;
                }
                Node<T> p = head;
                Node<T> r = new Node<T>();
                int j = 1;
                while (p.Next != null && j < i)
                {
                    r = p;
                    p = p.Next;
                    j++;
                }
                if (j == i)
                {
                    Node<T> q = new Node<T>(item);
                    q.Next = p;
                    r.Next = q;
                }
            }
            //删除单链表第i节点
            public T Delete(int i)
            {
                if(IsEmpty()||i<1)
                {
                    Console.WriteLine("链表为空或删除位置不允许");
                    return default(T);
                }
                Node<T> q = new Node<T>();
                if (i == 1)
                {
                    q = head;
                    head = head.Next;
                    return q.Data;
                }
                Node<T> p = head;
                int j = 1;
                while (p.Next != null && j < i)
                {
                    j++;
                    q = p;
                    p = p.Next;
                }
                if (j == i)
                {
                    q.Next = p.Next;
                    return p.Data;
                }
                else
                {
                    Console.WriteLine("删除的节点不存在");
                    return default(T);
                }
    
            }
            //获取单链表第i个数据元素
            public T GetElem(int i)
            {
                if (IsEmpty() || i < 1)
                {
                    Console.WriteLine("链表为空或者获取位置不允许");
                    return default(T);
                }
                Node<T> p = new Node<T>();
                p = head;
                int j = 1;
                while (p.Next != null && j < i)
                {
                    p = p.Next;
                    j++;
                }
                if (j == i)
                {
                    return p.Data;
                }
                else
                {
                    Console.WriteLine("要获取的节点不存在");
                    return default(T);
                }
            }
            //在单链表中查找值为value的节点
            public int Locate(T value)
            {
                if (IsEmpty())
                {
                    Console.WriteLine("链表为空");
                    return -1;
                }
                Node<T> p = new Node<T>();
                p = head;
                int i = 1;
                while (!p.Data.Equals(value) && p.Next != null)
                {
                    p = p.Next;
                    i++;
                }
                return i;
            }

    实现这些接口都不难,还是要理解链表的具体操作原理,只是记代码是没用的,不用多久就忘的差不多,p.Next等这些地方可以联想到C中的指针,不过C中的指针有时挺危险的,C#中的也许就安全多了吧。

    然后再玩玩一些经典题目,首先就是单链表倒置

            //-----------------------------------单链表扩展方法---------------------------------------------
            /// <summary>
            /// 单链表倒置
            /// </summary>
            /// <param name="H"></param>
            public void ReversLinkList(LinkList<T> H)
            {
                Node<T> p = H.head;
                Node<T> q = new Node<T>();
                H.head.Next = null;
                while (p != null)
                {
                    q = p;
                    p = p.Next;
                    q.Next = H.head.Next;
                    H.head.Next = q;
                }
            }

    再做个题目:构造单链表Hb,要求Hb只包含Ha表中所有值不相同节点

            /// <summary>
            /// 构造单链表Hb,要求Hb只包含Ha表中所有值不相同节点
            /// </summary>
            /// <param name="Ha"></param>
            /// <returns></returns>
            public LinkList<T> Purge(LinkList<T> Ha)
            {
                LinkList<T> Hb = new LinkList<T>();
                Node<T> p = Ha.head;
                Node<T> q = new Node<T>();
                Node<T> s = new Node<T>();
    
                s = p;
                p = p.Next;
                s.Next = null;
                Hb.head.Next = s;
                while (p != null)
                {
                    s = p;
                    p = p.Next;
                    q = Hb.head;
                    while(q!=null&&!(q.Data.Equals(s.Data)))
                    {
                        q = q.Next;
                    }
                    if(q==null)
                    {
                        s.Next = Hb.head;
                        Hb.head = s;
                    }
                }
                return Hb;
            }
  • 相关阅读:
    noip模拟赛 梦想
    noip模拟赛 水题
    noip模拟赛 猜数字
    Java基础知识强化64:基本类型包装类的引入
    Java基础知识强化63:Arrays工具类之方法源码解析
    Java基础知识强化62:Arrays工具类之概述和使用
    Java基础知识强化61:经典查找之 常见查找算法小结
    Java基础知识强化60:经典查找之二分查找
    Java基础知识强化59:String(字符串)和其他类型的相互转化
    Java基础知识强化58:经典排序之二叉树排序(BinaryTreeSort)
  • 原文地址:https://www.cnblogs.com/xmfdsh/p/3699998.html
Copyright © 2011-2022 走看看