循环数组实现一个队列

记录一下,等用到的时候直接copy, 不过这个不是线程安全的,如果需要多线程访问,需要加锁。

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

namespace test
{
    public class QueueNoSpaceException : Exception
    { }

    public class QueueEmptyException : Exception
    { }

    public class StorageQueue<T>
    {
        private int _size = 0;

        private T[] _buffer;

        private int _head = 0;
        private int _tail = 0;

        private int _remainingSpace = 0;

        public StorageQueue(int size)
        {
            if (size <= 0)
            {
                throw new ArgumentException("size is less or equal to zero");
            }
            _size = size + 1;
            _buffer = new T[_size];

            _head = _tail = 0;
            _remainingSpace = _size - 1;
        }

        public bool IsEmpty
        {
            get
            {
                if (_head == _tail) // empty
                    return true;
                else
                    return false;
            }
        }


        public bool IsFull
        {
            get
            {
                if ((_tail + 1) % _size == _head)
                { return true; }
                return false;
            }
        }

        public int RemainingSpaces
        {
            get { return _remainingSpace; }
        }

        public void Enqueue(T item)
        {
            if (item == null)
            { throw new ArgumentNullException("item"); }
            Enqueue(new T[1] { item });
        }

        public void Enqueue(T[] items)
        {
            if (items == null)
            { throw new ArgumentNullException("items"); }

            Enqueue(items, 0, items.Length);
        }

        public void Enqueue(T[] items, int offset, int count)
        {
            if (items == null)
            { throw new ArgumentNullException("items"); }

            if (offset < 0 || count <= 0 || items.Length < offset + count)
            { throw new ArgumentOutOfRangeException(); }

            if (IsFull || _remainingSpace < count)
            { throw new QueueNoSpaceException(); }

            lock (_buffer)
            {
                for (int i = 0; i < count; i++)
                {
                    _buffer[_tail++] = items[offset + i];
                    _tail = (_tail) % _size;
                }

                _remainingSpace -= count;
            }
        }

        public void Dequeue(out T item)
        {
            if (IsEmpty)
            { throw new QueueEmptyException(); }

            item = _buffer[_head++];
            _head = _head % _size;
            _remainingSpace++;

        }

        public void DequeueBlocking(out T item)
        {

            if (IsEmpty)
            { throw new QueueEmptyException(); }


            item = _buffer[_head++];
            _head = _head % _size;
            _remainingSpace++;

        }

        //dequeue "count" elements, return the dequeue number of elements
        public int Dequeue(ref T[] arr, int offset, int count)
        {
            if (arr == null)
            { throw new ArgumentNullException("arr"); }

            if (offset < 0 || count <= 0 || arr.Length < offset + count)
            { throw new ArgumentOutOfRangeException(); }

            if (IsEmpty)
            { throw new QueueEmptyException(); }


            int i = 0;
            do
            {
                arr[offset + i] = _buffer[_head++];
                i++;
                _head = _head % _size;
            } while (!IsEmpty && i < count);

            _remainingSpace += i;
            return i;

        }
    }
}


Unit Test

using System;
using System.Text;
using System.Collections.Generic;
using System.Net;
using Microsoft.VisualStudio.TestTools.UnitTesting;

using test;

namespace UTPCService.connection
{
    [TestClass]
    public class StorageQueueTest
    {
        [TestInitialize]
        public void Init()
        {
            _queue = new StorageQueue<byte>(_size);
        }

        private StorageQueue<byte> _queue;
        private const int _size = 10;

        [TestMethod]
        [ExpectedException(typeof(QueueNoSpaceException))]
        public void QueueFull_Test()
        {
            byte[] arr = new byte[_size + 1];
            _queue.Enqueue(arr);
        }

        [TestMethod]
        [ExpectedException(typeof(QueueEmptyException))]
        public void QueueEmpty_Test()
        {
            byte b = 0;
            _queue.Dequeue(out b);
        }

        [TestMethod]
        public void Queue_Item_Test()
        {
            byte b = 123;
            byte c = 0;
            _queue.Enqueue(b);
            _queue.Dequeue(out c);
            Assert.AreEqual(b, c);
        }

        [TestMethod]
        public void Queue_Array_Test()
        {
            byte[] b = { 123, 0, 126 };
            byte[] c = new byte[10];
            _queue.Enqueue(b);
            _queue.Dequeue(ref c, 0, b.Length);

            for (int i = 0; i < b.Length; i++)
            {
                Assert.AreEqual(b[i], c[i]);
            }
        }

        [TestMethod]
        public void Boundary_Test()
        {
            byte[] b = new byte[_size] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
            _queue.Enqueue(b);
            Assert.IsTrue(_queue.IsFull);

            byte[] c = new byte[10];
            _queue.Dequeue(ref c, 0, _size);
            Assert.IsTrue(_queue.IsEmpty);

            //change full position
            _queue.Enqueue(b, 0, 3);
            _queue.Dequeue(ref c, 0, 3);

            Assert.IsTrue(_queue.IsEmpty);

            _queue.Enqueue(b);
            Assert.IsTrue(_queue.IsFull);

            _queue.Dequeue(ref c, 0, _size);
            Assert.IsTrue(_queue.IsEmpty);
        }
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值