队列-顺序循环队列

你说的曾经没有我的故事 提交于 2020-03-12 02:34:22

顺序队列(Sequence Queue)用一片连续的存储空间来存储队列中的数据元素. 用一维数组来存放顺序队列中的数据元素。 队头位置设在数组下标为 0 的端,用 front 表示; 队尾位置设在数组的另一端,用 rear 表示。  front 和 rear 随着插入和删除而变化。 当队列为空时, front=rear=0。 因为在出队列(删除元素)的时候,需要花费大量 的时间移动大量元素,速度很慢,所以很少有实际 应用。

循环顺序队列,为了避免大量数据的移动,通常将一维数组的各个元素看成一个收尾相接的封闭的圆环,即第一个元素是最后一个元素的下一个元素,这种形式的顺序队列成为循环顺序队列(Circular sequence Queue)。 C#为我们提供的Queue类就是循环队列。

 

namespace 队列
{
    /// <summary>
    /// 链队列的 节点类
    /// </summary>
    /// <typeparam name="T"></typeparam>
    class QueueNode<T>
    {
        public T data;
        public QueueNode<T> next;
        public QueueNode(T _data) {
            this.data = _data;
        }
        public override string ToString()
        {
            return data.ToString();
        }
    } 
}
namespace 队列
{
    interface IQueueDS<T>
    {
        int Count { get; }//获取元素个数
        int GetLength();
        bool IsEmpty(); //是否为空队列
        void Clear(); //清空队列
        void Enqueue(T item); //入队
        T Dequeue(); //出队
        T Peek(); //取队头元素
    } 
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 队列
{
    /// <summary>
    /// 顺序循环队列
    /// </summary>
    /// <typeparam name="T"></typeparam>
    class CSeqQueue<T> : IQueueDS<T>
    {
        //存放元素的数组
        public T[] _array;
        //增长因子 1-10之间
        private int _growfactor;
        //最小增长值
        private const int _MinimumGrow = 4;
        //默认队列空间的大小
        private const int _defaultCapacity = 8;
        //元素的个数
        private int _size = 0;
        //队头指针  指向队头的第一个元素
        private int _head;
        //队尾指针  指向队尾的最后一个元素索引+1
        private int _tail;
        public CSeqQueue() : this(_defaultCapacity,2){ }
        public CSeqQueue(int capacity, float growFactor) {
            if (capacity < 0) {
                throw new ArgumentOutOfRangeException("capacity","初识容量不能小于0");
            }
            if (capacity < _defaultCapacity) {
                capacity = _defaultCapacity;
            }
            if (growFactor < 1.0 || growFactor > 10.0) {
                throw new ArgumentOutOfRangeException("growFactor","增长因子必须在1-10之间");
            }
            this._array = new T[capacity];  //初始化数组
            this._head = this._tail = 0;
            this._size = 0;
            this._growfactor = (int)(growFactor * 100f);
        }
        //获取元素个数
        public int Count {
            get {
                return this._size;
            }
        }
        public void Clear()
        {
            this._head = this._tail = this._size = 0;
        }
        //出队操作
        public T Dequeue()
        {
            if (this._size == 0)
            {
                throw new InvalidOperationException("队列下溢,队里里没有数据");
            }
            T obj = this._array[_head]; //出队数据
            this._array[_head] = default(T);        //在数组里删除出队元素
            this._head = (this._head + 1) % this._array.Length;   //循环队列  处理机制,保证下标是循环的
            this._size--;
            return obj;
        }
        //入队
        public void Enqueue(T item)
        {
            if (this._size == this._array.Length) {
                //计算新的容量
                int capacity = (int)(this._array.Length * this._growfactor / 100f);
                if (capacity < this._array.Length + _MinimumGrow) {
                    //最少要增长四个元素
                    capacity = this._array.Length + _MinimumGrow;
                }
                //调整容量
                SetCapacity(capacity);
            }
            this._array[_tail] = item;  //入队
            this._tail = (this._tail + 1) % this._array.Length;     //移动尾巴指针
            this._size++;
        }
        private void SetCapacity(int capacity) {    //内存搬家
            T[] destinationArray = new T[capacity];
            if (this._head < this._tail)
            {
                //头指针在尾指针的前面
                Array.Copy(this._array, this._head, destinationArray, 0, this._size);
            }
            else {
                //头指针在尾指针的后面
                Array.Copy(this._array, this._head, destinationArray, 0, this._array.Length-this._head);
                Array.Copy(this._array, 0, destinationArray, this._array.Length - this._head, this._tail);
            }
            this._array = destinationArray;
            this._head = 0;
            this._tail = (this._size == capacity) ? 0 : this._size;
        }
        public int GetLength()
        {
            return this._size;
        }
        public bool IsEmpty()
        {
            return this._size == 0;
        }
        //获取队头元素,不删除
        public T Peek()
        {
            if (this._size == 0) {
                throw new InvalidOperationException("队列下溢,队里里没有数据");
            }
            T obj = this._array[_head]; //出队数据 
            return obj;
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 队列
{
    class Program
    {
        static void Main(string[] args)
        {
            //创建一个队列对象
            //Queue<int> queue = new Queue<int>();
            //创建一个循环顺序列表
            IQueueDS<int> queue = new CSeqQueue<int>();
            ////创建一个链队列
            //IQueueDS<int> queue = new LinkedQueue<int>();
            queue.Enqueue(10);  //入队操作,  队头位置
            queue.Enqueue(20);
            queue.Enqueue(30);
            queue.Enqueue(40);  //队尾
            Console.WriteLine("入队数据是 10,20,30,40,队列元素个数为 :"+queue.Count);
            int dq = queue.Dequeue();    //出队,返回出队数据
            Console.WriteLine("Dequeue 出队操作,数据为:"+dq+",队列元素个数为: "+queue.Count);

            int pk = queue.Peek();//只获取队头数据,不做出队操作
            Console.WriteLine("Peek 获取数据为:" + pk + ",队列元素个数为: " + queue.Count);

            queue.Clear();      //清空队列
            Console.WriteLine("Clear 清空操作,队列元素个数为: " + queue.Count);



            Console.WriteLine("=================================华丽分割线====================================");
            IQueueDS<string> cQueue = new CSeqQueue<string>();
            for (int i = 1; i < 8; i++)
            {
                cQueue.Enqueue("a"+i);  //1,2
            }
            for (int i = 0; i < 4; i++)
            {
                cQueue.Dequeue();
            }
            for (int i = 8; i < 13; i++)
            {
                cQueue.Enqueue("a" + i);  //efg
            }
            for (int i = 0; i < 4; i++)
            {
                cQueue.Dequeue();
            }
            Console.WriteLine("cQueue 获取数据为:" + cQueue.Peek() + ",队列元素个数为: " + cQueue.Count);
            Console.ReadKey();
        }
    }
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!