C#数据结构08:有序数组

说明
(此系列帖子记录数据结构学习成果,如侵犯视频作者权益,立删)
作者账号 哔哩哔哩:离忧夏天

基于二分查找的核心方法Rank=>用于寻找元素

public int Rank(Key key)
{
    //在[l~r]范围里寻找key
    int l = 0;
    int r = N - 1;

    while (l <= r)
    {
        int mid = l + (r - l) / 2;

        if (key.CompareTo(keys[mid]) < 0)
            r = mid - 1;    //mid左侧查找key
        else if (key.CompareTo(keys[mid]) > 0)
            l = mid + 1;    //mid右侧查找key
        else    //key.CompareTo(keys[mid]) == 0
            return mid;     
    }

    return l;//未找到key,返回l
}

有序数组

方法有序数组
Rank(私有方法用于查询传入参数key所对应的索引
Add添加元素
Remove移除元素
Min返回列表最小值
Max返回列表最大值
Select根据传入的索引,返回对应的数
Contains是否包含元素
Floor找出小于或等于key的最大键
Ceiling找出大于或等于key的最小键
ResetCapacity(私有方法)调整数组容量大小

(支持存储一种数据)

有序数组里的数据首先必须是支持比较的(否则无法进行排序),即实现key实现IComparable <key> 接口

需要注意的是,对于查找key的操作,

  • 如果是命中查询:索引i一定在数组中
  • 如果是未命中查询:索引i不一定在数组中,这是因为未命中查询时,l > r,可能存在r=N-1,l =N,导致了索引i越界。

因此在调用Rank方法后,我们需要判断索引 i 是否在数组中。

namespace List
{
    //where Key:IComparable<Key> 对Key进行泛型约束,限定Key类型,不能是任意类型
    class SortedArray1<Key> where Key : IComparable<Key>
    {
        private Key[] keys;
        private int N;

        public SortedArray1(int capacity)
        {
            keys = new Key[capacity];
        }

        public SortedArray1() : this(10) { }

        public int Count =>N;

        public bool IsEmpty => N == 0; 

        public int Rank(Key key)
		{
    		//在[l~r]范围里寻找key
    		int l = 0;
    		int r = N - 1;

    		while (l <= r)
    		{
        		int mid = l + (r - l) / 2;

        		if (key.CompareTo(keys[mid]) < 0)
            		r = mid - 1;    //mid左侧查找key
        		else if (key.CompareTo(keys[mid]) > 0)
            		l = mid + 1;    //mid右侧查找key
        		else    //key.CompareTo(keys[mid]) == 0
            		return mid;     
    		}

    		return l;//未找到key,返回l
		}
		
        public void Add(Key key)
        {
            int i = Rank(key);

            if (N == keys.Length)
                ResetCapacity(2 * keys.Length);

            if (i < N && keys[i].CompareTo(key) == 0)
                return;

            for (int j = N - 1; j >= i; j--)
                keys[j + 1] = keys[j];

            keys[i] = key;
            N++;
        }

        public void Remove(Key key)
        {
            if (IsEmpty)
                return;

            int i = Rank(key);

            if (i == N || keys[i].CompareTo(key) != 0)
                return;

            for (int j = i + 1; j <= N - 1; j++)
                keys[j - 1] = keys[j];

            N--;
            keys[N] = default(Key);

            if (N == keys.Length / 4)
                ResetCapacity(keys.Length / 2);
        }

        public Key Min()
        {
            if (IsEmpty)
                throw new ArgumentException("数组为空");

            return keys[0];
        }
		//获取数组最大值
        public Key Max()
        {
            if (IsEmpty)
                throw new ArgumentException("数组为空");

            return keys[N - 1];
        }
		//获取数组最大值
        public Key Select(int k)
        {
            if (k < 0 || k >= N)
                throw new ArgumentException("索引越界");

            return keys[k];
        }

        public bool Contains(Key key)
        {
            int i = Rank(key);

            if (i < N && keys[i].CompareTo(key) == 0)
                return true;
            return false;
        }

        //找出小于或等于key的最大键
        public Key Floor(Key key)
        {
            int i = Rank(key);

            if (i < N && keys[i].CompareTo(key) == 0)
                return keys[i];

            if (i == 0)
                throw new ArgumentException("没有找到小于或等于" + key + "的最大键");
            else
                return keys[i - 1];
        }

        //找出大于或等于key的最小键
        public Key Ceiling(Key key)
        {
            int i = Rank(key);

            if (i == N)
                throw new ArgumentException("没有找到大于或等于" + key + "的最小键");
            else
                return keys[i];
        }

        //调整数组容量的大小
        private void ResetCapacity(int newCapacity)
        {
            Key[] newKeys = new Key[newCapacity];
            for (int i = 0; i < N; i++)
                newKeys[i] = keys[i];

            keys = newKeys;
        }

        //输出数组类的信息
        public override string ToString()
        {
            StringBuilder res = new StringBuilder();
            res.Append("[");
            for (int i = 0; i < N; i++)
            {
                res.Append(keys[i]);
                if (i != N - 1)
                    res.Append(", ");
            }
            res.Append("]");
            return res.ToString();
        }
    }
}

(支持存储两种数据)

和一种数据的类似,只不过现在支持传入两个参数,但是key仍然必须是支持比较的

namespace List
{
    class SortedArray2<Key,Value> where Key : IComparable<Key>
    {
        private Key[] keys;
        private Value[] values;
        private int N;

        public SortedArray2(int capacity)
        {
            keys = new Key[capacity];
            values = new Value[capacity];
        }

        public SortedArray2() : this(10) { }

        public int Count { get { return N; } }

        public bool IsEmpty => N == 0;


        public int Rank(Key key)
        {
            //在[l-r]中寻找key
            int l = 0;
            int r = N-1;

            while (l <= r)
            {
                int mid = l + (r - l) / 2;

                if (key.CompareTo(keys[mid]) < 0)
                    r = mid - 1;

                else if (key.CompareTo(keys[mid]) > 0)
                    l = mid + 1;

                else
                    return mid;//找到key并返回索引下标
            }
            return l;
        }

        public Value Get(Key key)
        {
            if (IsEmpty)
                throw new ArgumentException("数组为空");

            int i =Rank(key);

            if (i<N && keys[i].CompareTo(key) == 0)
                return values[i];
            else
                throw new ArgumentException("键"+key+ "不存在");
        }
        public void Add(Key key,Value value)
        {
            int i = Rank(key);

            if (N == keys.Length)
                ResetCapacity(2 * keys.Length);

            if (i < N && keys[i].CompareTo(key) == 0)
            {
                values[i] = value;
                return;
            }

            for (int j = N - 1; j >= i; j--)
            {
                keys[j + 1] = keys[j];
                values[j + 1] = values[j];
            }

            keys[i] = key;
            values[i] = value;
            N++;
        }

        public void Remove(Key key)
        {
            if (IsEmpty)
            {
                return;
            }
            int i = Rank(key);

            if (i == N || keys[i].CompareTo(key) != 0)
                return;

            for (int j = i + 1; j <= N - 1; j++)
            {
                keys[j - 1] = keys[j];
                values[j-1] = values[j];
            }

            N--;
            keys[N] = default(Key);
            values[N] = default(Value);

            if (N == keys.Length / 4)
                ResetCapacity(keys.Length / 2);

        }
        //获取最小键
        public Key Min()
        {
            if (IsEmpty)
                throw new ArgumentException("数组为空");

            return keys[0];
        }
        //获取最大键
        public Key Max()
        {
            if (IsEmpty)
                throw new ArgumentException("数组为空");

            return keys[N-1];
        }
        //选出排名为k的键
        public Key Select(int k)
        {
            if (k == 0 || k >= N)
                throw new ArgumentException("索引越界");

            return keys[k];
        }

        //查找是否在数组中
        public bool Contains(Key key)
        {
            int i = Rank(key);

            if (i < N && keys[i].CompareTo(key) == 0)
                return true;

            return false;
        }
        //找出小于或等于key的最大键
        public Key Floor(Key key)
        {
            int i = Rank(key);

            if (i < N && keys[i].CompareTo(key) == 0)
                return keys[i];

            if (i == 0)
                throw new ArgumentException("没有找到小于和等于" + key + "的最大值");

            else
                return keys[i - 1];
        }
        //找出大于或等于key的最大键
        public Key Ceiling(Key key)
        {
            int i = Rank(key);

            if (i == N)
                throw new ArgumentException("没有找到大于和等于" + key + "的最大值");
            else
                return keys[i];
        }

        //调整数组容量的大小
        private void ResetCapacity(int newCapacity)
        {
            Key[] newKeys = new Key[newCapacity];
            Value[] newValues = new Value[newCapacity];

            for (int i = 0; i < N; i++)
            {
                newKeys[i] = keys[i];
                newValues[i] = values[i];
            }

            keys = newKeys;
            values = newValues;
        }
        //输出有序数组的信息
        public override string ToString()
        {
            StringBuilder res = new StringBuilder();

            res.Append("[");
            for (int i = 0; i < N; i++)
            {
                res.Append("{" + keys[i] + "," + values[i] + "}");
                    if (i != N - 1)
                    res.Append(", ");
            }
            res.Append("]");
            return res.ToString();
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值