• 数据结构学习之线性表(二)


    开篇:上次我们讲到,实现基本的数组的增删改查。现在我们来优化和改善,并且分析一下。

    1. 首先我们定义的数组类型 不支持泛型。

    2. 当容量不够使用的时候, 应该可以自动触发扩容操作。

    我们来实现一下。我们使用泛型的T类型来代表。

    public class Array<T>
        {
            private T[] Data;
            private int Size;
            private int Capacity;
            public bool IsFull => this.Capacity == this.Size;
            public Array(int capacity = 20)
            {
                this.Capacity = capacity;
                this.Data = new T[this.Capacity];
            }
    }

    此时 增删改查都应该操作泛型T变量

    比如 add ,此时我们增加扩容操作,我们来新增个数组 遍历复制操作,容量的大小应该视数组的容量大小来定。

    public void Add(T value)
            {
                if (IsFull)
                    this.ExpandCapacity(this.Capacity * 2);
                this.Size++;
                this.Data[this.Size - 1] = value;
            }
    }
    private void ExpandCapacity(int capacity)
     {
            var newData = new T[capacity];
            for (int i = 0; i < newData.Length; i++)
            {
                newData[i] = this.Data[i];
            }
            this.Data = newData;
            this.Capacity = capacity;
     }

    删除操作

    public T Delete(int index)
    {
            if (index < 0)
                throw new Exception("index is less than zero");
            if (index > this.Capacity-1)
                throw new Exception("index is more than capacity");
            if (index > this.Size-1)
                return default;
            var value = this.Data[index];
            for (int i = index; i < this.Size-1; i++)
            {
                this.Data[i] = this.Data[i+1];
            }
            this.SetEmpty(this.Size-1);
            this.Size--;
            if (this.Size <= this.Capacity/2)
               this.NarrowCapacity(this.Capacity / 2);
            return value;
     }
    
    private void NarrowCapacity(int capacity)
    {
            var newData = new T[capacity];
            for (int i = 0; i < this.Data.Length; i++)
            {
                newData[i] = this.Data[i];
            }
             this.Data = newData;
             this.Capacity = capacity;
    }

    此时查找等需要比较的操作 需要 T类型去重写 object基类的Equals()规则

    public bool IsContain(int value)
    {
            var isContain = false;
            for (int i = 0; i < this.Size; i++)
            {
                if (this.Data[i].Equals(value))
                    isContain = true;
            }
            return isContain;
    }

    此时我们来看我们的算法的复杂度

    1.增加 O(1) 这个没什么好说 ,但如果已满,触发了扩容复杂度为 O(n)。

    2.插入  插入的话,如果插入的index为Size ,此时的复杂度为 O(1) ,但最坏情况下为插入到第一个,此时的复杂度为 O(n),平均复杂度为(n/2),还是 O(n)

    3.删除 删除也是一样。也会有最坏情况,复杂度为 O(n).

    4.查找 O(1) 

    但是有个问题,比如,此时的容量已满我们增加了一个,触发扩容,此时又删除最后一个,此时的数组的Size为容量的一半,又要缩容器。都是O(1)的操作,此时的复杂度就会是O(n),(复杂度震荡),此时我们可以改一下。当size小于容器的1/4,才触发缩容器。避免了这种又增又删O(1)一次的操作带来的复杂度震荡。

    if (this.Size <= this.Capacity/4)
                   this.NarrowCapacity(this.Capacity / 2);

    如下我的项目的 Github地址  有需要的同学可以自取哦 地址: https://github.com/GuanZhengXin/DataStruct

    这样我们就简单实现了一个基本的数组结构,下期我们来学习一下栈的结构和实现。

  • 相关阅读:
    Zookeeper and The Infinite Zoo(CF1491D)(位运算)
    树上差分
    最近公共祖先
    极角排序
    最长路spfa
    树的基础
    树的遍历~
    最小圆覆盖板子
    动态凸包(询问点是否在凸包内部)
    凸包内最大三角形
  • 原文地址:https://www.cnblogs.com/GuanZx/p/11037208.html
Copyright © 2020-2023  润新知