c#数据结构单链表基本操作实现

本文根据https://www.cnblogs.com/wjcnet/p/3424533.html文章理解,感谢博主。

在数据结构中一般多用c语言实现,因为本身是学习c#,所以今天想通过c#来实现单链表的一些操作,菜鸟写的不好不要见怪,欢迎大家指出问题。

程序大致结构如下:

下面来看看主要类:

namespace LinkList
{
    class Node<T>
    {
        private T date;//数据域
        private Node<T> next;//引用域

        public T Date { get => date; set => date = value; }
        internal Node<T> Next { get => next; set => next = value; }
        public Node()
        {
            Date = default(T);
            Next = null;
        }
        public Node(T val)
        {
            Date = val;
        }
        public Node(T val,Node<T> p)
        {
            Date = val;
            Next = p;
        }
        public Node(Node<T> p)
        {
            Next = p;
        }
     
    }
}

IListDs接口:

namespace LinkList
{
    public interface IListDs<T>
    {
        int GetLength();//求长度
        void Clear();//清空操作
        bool IsEmpty();//判断是不是空
        void Append(T item);//在链表尾部添加
        void Insert(T item, int i);//插入操作
        T Delete(int i);//删除操作
        T GetElem(int i);//取表元
        int Locate(T value);//按值查找
    }
}

Link类:

该类用来实现接口中的方法,以一个一个方法的形式来方便理解。前面的清空,获取长度等方法我就不解释了,稍微看下就能够理解。

//在链表末尾添加
        //通过找到最后一个节点然后与新节点连接起来
        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;//将头节点给节点p;
            while (p.Next!=null)//可以理解为p.Next.Next......
            {
                p = p.Next;
            }
            p.Next = q;//将新的节点与最后一个节点连接起来
        }
  //在i之前插入
        //将插位置之前节点指针域指向新节点,并且新节点指针域指向插入位置之后的节点
        public void Insert(T item, int i)
         {
            if (IsEmpty() || i < 1)
            {
                Console.WriteLine("链表为空或者位置错误");
                return;
            }
            //当插入位置是1之前,将新节点指针域指向原来的第一个节点,头指针指向新节点
            if (i == 1)
            {
                Node<T> q = new Node<T>(item);
                //因为是在第一个点之前插入所以直接将新节点指针域指向原来头节点,再将新节点设为头结点
                //如果是在第一个点之后插入,q.next = head.next,将原来头节点指向的下个节点的指针域赋给新节点的指针域
                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);
                Node<T> m = r.Next;
                r.Next = q;
                q.Next = m;
                
            }
        }

个人认为比较难理解的就是以上两个方法,下面来看看整个Link类:


namespace LinkList
{
    public class Link<T> : IListDs<T>
    {
        private Node<T> head;//单链表的头引用

        internal Node<T> Head { get => head; set => head = value; }

        public Link()
        {
            head = null;
        }

        public void Clear()
        {
            head = null;
            
        }

        //获取表长
        public int GetLength()
        {
            int Length = 0;
            Node<T> p = head;
            while (p!=null)
            {
                p = p.Next;
                Length++;
            }
            return Length;
        }

        public bool IsEmpty()
        {
            return head == null;
        }

        //在链表末尾添加
        //通过找到最后一个节点然后与新节点连接起来
        public void Append(T item)
        {   //创建要插入的新的节点
            Node<T> q = new Node<T>(item);
            
            Node<T> p = new Node<T>();
            if (head == null)
            {
                head = q;
                //q.Next = head//如果循环链表的话加上这
                return;
            }
            p = head;//将头节点给节点p;
            while (p.Next!=null)//可以理解为p.Next.Next......
            {
                p = p.Next;
            }
            p.Next = q;//将新的节点与最后一个节点连接起来
            //q.Next = head//如果循环链表的话加上这
        }

        //在i之前插入
        //将插位置之前节点指针域指向新节点,并且新节点指针域指向插入位置之后的节点
        public void Insert(T item, int i)
         {
            if (IsEmpty() || i < 1)
            {
                Console.WriteLine("链表为空或者位置错误");
                return;
            }
            //当插入位置是1之前,将新节点指针域指向原来的第一个节点,头指针指向新节点
            if (i == 1)
            {
                Node<T> q = new Node<T>(item);
                //因为是在第一个点之前插入所以直接将新节点指针域指向原来头节点,再将新节点设为头结点
                //如果是在第一个点之后插入,q.next = head.next,将原来头节点指向的下个节点的指针域赋给新节点的指针域
                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);
                Node<T> m = r.Next;
                r.Next = q;
                q.Next = m;
                
            }
        }

        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)
            {
                q = p;
                p = p.Next;
                j++;
            }
            if (j == i)
            {
                q.Next = p.Next;
                return p.Data;
            }
            else
            {
                Console.WriteLine("位置不正确");
                return default(T);
            }
        }

        public T GetElem(int i)
        {
            if (IsEmpty())
            {
                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);
        }

        public int Locate(T value)
        {
            if (IsEmpty())
            {
                Console.WriteLine("链表是空链表!");
                return -1;
            }
            Node<T> p = new Node<T>();
            p = head;
            int i = 1;
            while (((p.Next != null) && (!p.Data.Equals(value))))
            {
                p = p.Next;
                i++;
            }
            if (p == null)
            {
                Console.WriteLine("不存在这样的节点。");
                return -1;
            }
            else
            {
                return i;
            }
        }
    }
}

需要注意的是Next是一个节点类型:

单链表的c#实现就暂时到这里,以后有我会继续补充。本篇博客只是用来记录学习中的问题,提升自己,如果能够帮到别人更加好,有什么错误的地方欢迎大家指出来一起讨论,一起进步!!!

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值