码迷,mamicode.com
首页 > 其他好文 > 详细

C#单链表(数据结构)

时间:2014-07-22 23:13:13      阅读:495      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   java   color   数据   

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

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

节点的形象图如下:

mamicode.com,码迷

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

mamicode.com,码迷
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;
            }
        }
    }
mamicode.com,码迷

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

mamicode.com,码迷

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

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

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

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

mamicode.com,码迷
        //求单链表长度
        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;
        }
mamicode.com,码迷

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

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

mamicode.com,码迷
        //-----------------------------------单链表扩展方法---------------------------------------------
        /// <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;
            }
        }
mamicode.com,码迷

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

mamicode.com,码迷
        /// <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;
        }
mamicode.com,码迷

 

C#单链表(数据结构),码迷,mamicode.com

C#单链表(数据结构)

标签:style   blog   http   java   color   数据   

原文地址:http://www.cnblogs.com/xmfdsh/p/3699998.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!