线性表(顺序表,链表等)及其实现(C#版)

线性表

线性表的实现方式有下面几种

1.顺序表

线性表的顺序存储是指在内存中用一块地址连续的空间依次存放线性表的数据元素,用这种方式存储的线性表叫顺序表,它的实现主要依赖于数组。

(1)空间上:
顺序表的实现一般是实现连续开辟一段空间,然后在进行数据的增删查改,所以当我们不知道要存储多少数据时,用顺序表来开辟的空间如果太大,就会造成一定程度上的浪费,
(2)时间上:
访问随机元素的时间复杂度:由于支持数组下标访问,所以顺序表访问随机元素的时间复杂度是O(1)。
随机位置插入、删除元素的时间复杂度:
因为顺序表的元素是连续存储的,因此要在特定位置插入、删除元素需要把它之后的元素全部后移或前移一个元素的位置,时间开销比较大

顺序表的实现:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _线性表
{
    //IComparable<T>接口定义由值类型或类实现的特定于类型的通用比较方法,旨在对其实例进行排序。
    public class SelfList<T> where T:IComparable
    {
        //T GetItem(int index);//获取索引对应的值
        //void Add(T item);//增添元素的方法    
        //void Insert(int index, T item);  //插入元素的方法
        //void RemoveAt(int index); // 移除对应指定索引处的元素。
        //int IndexOf(T item);//搜索指定的对象,并返回整个 System.Collections.Generic.List`1 中第一个匹配项的从零开始的索引。
        //int LastIndexOf(T item); //搜索指定的对象,第一个匹配项的从最后开始的索引。                               
        //void Sort();//从小到大排序
        int count;
        T[] arry;
 
        public int Count { get => count;}
        public int Capacity{ get => arry.Length; }//容量,用于扩容

        public SelfList(int size)
        {
            arry = new T[size];
        }
        public SelfList()
        {
            arry = new T[4];//没有指定size时,默认为4
        }

        public T GetItem(int index)
        {
            if (index>=0&&index<Count)
            {
                return arry[index];
            }
            else
            {
                throw new Exception("索引超出范围");
            }
        }


        //通过索引器访问
        public T this[int index]
        {
            get
            {
                return GetItem(index);

            }
            set
            {
                if (index >= 0 && index < Count)
                {
                    arry[index] = value;
                }
                else
                {
                    throw new Exception("索引超出范围");
                }
            }
        }

        public void Add(T item)
        {
            if (Count==Capacity)
            {
                T[] newarry = new T[Count * 2];
                Array.Copy(arry, newarry, Count);
                arry = newarry;
            }
            arry[Count] = item;
            count++;
        }

        public void Insert(int index, T item)
        {
            if (index>=0&&index<=Count)//可以插入最后一位
            {
                if (Count == Capacity)
                {
                    T[] newarry = new T[Count * 2];
                    Array.Copy(arry, newarry, Count);
                    arry = newarry;
                }

                for (int i = Count-1; i >= index; i--)
                {
                    arry[i + 1] = arry[i];
                }
                arry[index] = item;
                count++;
            }
            else
            {
                throw new Exception("索引超出范围");
            }


        }
        public int IndexOf(T item)
        {
            for (int i = 0; i < count; i++)
            {
                if (arry[i].Equals(item))
                {
                    return i;
                }
            }
            return -1;
        }
        public int LastIndexOf(T item)
        {
            for (int i = Count; i >=0; i--)
            {
                if (arry[i].Equals(item))
                {
                    return i;
                }
            }
            return -1;
        }

        public void RemoveAt(int index)
        {
            
             if (index >= 0 && index < Count)
             {
              
                for (int i = index; i < count-1; i++)
                {
                    arry[i - 1] = arry[i];
                }
                count--;
             }
            else
            {
                throw new Exception("索引超出范围");
            }

            
        }




        //         CompareTo(Object) 必须返回 Int32 具有以下三个值之一的,如下表所示。
        //注解
        //“值”	                含义
        //小于零     当前实例 CompareTo 在排序顺序中位于方法所指定的对象之前。
        //等于零    前实例与方法所指定的对象在排序顺序中出现的位置相同 CompareTo 。
        //大于零     此当前实例 CompareTo 在排序顺序中跟随方法所指定的对象之后。
    
    public void Sort()
        {
            for (int i = 0; i < Count-1; i++)
            {
                for (int j = 0; j < Count-i-1; j++)
                {
                    if (arry[j].CompareTo(arry[j+1])>0)
                    {
                        T tem = arry[j+1];
                        arry[j+1] = arry[j];
                        arry[j] = tem;
                    }
                }
            }
        }
    }
}

单链表

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

在这里插入图片描述

下图是线性表(a1,a2,a3,a4,a5,a6)对应的链式存储结构示意图。
在这里插入图片描述

(1)空间上:
单链表则是一次只开辟一个结点的空间,用来存储当前要保存的数据及指向下一个结点或NULL的指针,但由于每次开辟的空间不是连续的,容易形成碎片空间,造成空间的浪费
(2)时间上:

**访问随机元素的时间复杂度:**单链表的数据是链式存储的,它的元素是不支持随机访问的,想要知道某个元素,只能从头结点开始遍历整个链表,直到找到了该元素为止。
所以单链表访问随机元素的平均时间复杂度是O(n)。
随机位置插入、删除元素的时间复杂度:
单链表在插入或删除元素时,只需要改变它的前驱节点及插入或删除元素的指向即可,所以单链表在插入随机位置插入、删除元素的时间复杂度是O(1)。

链式表的实现

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _线性表
{
    /// <summary>
    /// 链式表(单向链表)
    /// </summary>
    class Chain<T> where T:IComparable
    {
        //T GetItem(int index);//获取索引对应的值
        //void Add(T item);//增添元素的方法    
        //void Insert(int index, T item);  //插入元素的方法
        //void RemoveAt(int index); // 移除对应指定索引处的元素。
        //int IndexOf(T item);//搜索指定的对象,并返回整个 System.Collections.Generic.List`1 中第一个匹配项的从零开始的索引。
        //int LastIndexOf(T item); //搜索指定的对象,第一个匹配项的从最后开始的索引。                               
        //void Sort();//从小到大排序
        int count;
        Node<T> head;

        public Chain()
        {
            head = null;
        }

        public int Count { get => count; }

        public T GetItem(int index)
        {
            if (index >= 0 && index < Count)
            {
               
                    Node<T> temp = head;
                    for (int i = 1; i <= index; i++)
                    {
                        temp = temp.next;
                    }
                  return temp.deta;
            }
            else
            {
                throw new Exception("索引超出范围");
            }
        }


        //通过索引器访问
        public T this[int index]
        {
            get
            {
                return GetItem(index);

            }
            set
            {
                if (index >= 0 && index < Count)
                {
                    Node<T> temp = head;
                    for (int i = 0; i < index; i++)
                    {
                        temp = temp.next;
                    }
                    temp.deta = value;
                }
                else
                {
                    throw new Exception("索引超出范围");
                }
            }
        }

        public void Add(T item)
        {
             Node<T> newnode = new Node<T>(item);
            if (head==null)
            {//第一个节点为头节点时
                head = newnode;
            }
            else
            {//第一个节点不是头节点时,把新节点放在链表末尾
                Node<T> temp = head;
                while (temp.next!=null)
                {
                    temp = head.next;
                }

                temp.next = newnode;
            }
            count++;
        }

        public void Insert(int index, T item)
        {
            Node<T> newnode = new Node<T>(item);
            if (index == 0)
            {//插入位置为第一个节点时

                head= newnode;
                newnode.next = head.next;
            }
            else
            {//插入位置为不是第一个节点时,获取插入位置的结点(currentNode)和插入位置前一个结点(preNode),
             //使插入位置前一个结点(preNode)指向新节点(newNode),新节点(newNode)指向插入位置的结点(currentNode)
                Node<T> temp = head;
                for (int i = 1; i <= index-1; i++)
                {
                    temp = temp.next;
                }
                Node<T> preNode = temp;
                Node<T> currentNode = temp.next;
                temp.next = newnode;
                newnode.next = currentNode;
            }
            count++;
        }
        public int IndexOf(T item)
        {
            Node<T> temp = head;
            int index = 0;
            while (temp!=null)
            {               
                if (temp.deta.Equals(item))
                {
                    return index;
                }
                index++;
                temp = temp.next;
            }
            return -1;
        }
        public int LastIndexOf(T item)
        {
            Node<T> temp = head;
            int index = 0;
            T[] array = new T[Count];
            while (temp != null)
            {
                array[index++] = temp.deta;
                temp = temp.next;
            }
            for (int i = index-1; i >=0; i++)
            {
                if (array[i].Equals(item))
                {
                    return i;
                }
            }
            return -1;
        }

        public void RemoveAt(int index)
        {           
            if (index == 0)
            {//移除位置为第一个节点时

                head = head.next;
              
            }
            else
            {//移除位置为不是第一个节点时,获取移除位置前一个结点(preNode),移除位后置一个结点(nextNode)
             //使移除位置前一个结点(preNode)指向移除位后置一个结点(nextNode)
                Node<T> temp = head;
                for (int i = 1; i <= index - 1; i++)
                {
                    temp = temp.next;
                }
                Node<T> preNode = temp;
                Node<T> nextNode = temp.next.next;
                preNode.next = nextNode;
            }
            count--;
        }

        public void Sort()
        {
            //获取所有节点位置
            Node<T> temp = head;
            Node<T>[] detas = new Node<T>[Count];
            for (int i = 0; i < Count; i++)
            {
                detas[i] = temp;
                temp = temp.next;
            }


            //冒泡排序
            for (int i = 0; i < Count - 1; i++)
            {
                for (int j = 0; j < Count - i - 1; j++)
                {
                    if (detas[j].deta.CompareTo(detas[j+1].deta)>0)
                    {
                        T temdeta = detas[j].deta;
                        detas[j].deta = detas[j + 1].deta;
                        detas[j+1].deta = temdeta;
                    }

                }
            }
        }

       

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值