C#队列

183 阅读3分钟

队列

队列(Queue)是插入操作限定在表的尾部而其他操作限定在表头的线性表。

队列操作按照先进先出,后进后出的原则进行。主要操作包括在队尾插入元素、在队头删除元素、取队头元素和判空等。

BCL中的队列

C#2.0以下版本提供了非泛型的Queue类

C#2.0以上提供了泛型Queue类

常用方法:

  • Enqueue() 入队,放在队尾
  • Dequeue() 出队,移除队首元素,并返回被移除的元素
  • Peek() 获取队首元素,不删除
  • Clear() 清空元素
  • Count() 获取队列中元素的个数

队列接口定义

public interface IQueue<T>
    {
        int Count { get; }
        int GetLength();
        bool IsEmpty();
        void Clear();
        void Enqueue(T item);
        T Dequeue();
        T Peek();
    }

顺序队列

用一片连续的存储空间来存储队列中的数据元素,这样的队列称为顺序队列(Sequence Queue)。类似于顺序栈,用一维数组来存放顺序队列中的数据元素。队头位置设在数组下标为0的一端,用front表示。队尾设置在另一端,用rear表示。当队列为空时,front=rear=-1。

顺序队列实现

public class SeqQueue<T>:IQueue<T>
    {
        private T[] data;
        private int count;//当前有多少个元素
        private int front;//队首,队首元素索引-1
        private int rear;//队尾,队尾元素索引

        public SeqQueue(int size)
        {
            data = new T[size];
            count = 0;
            front = -1;
            rear = -1;
        }

        public SeqQueue() : this(10)
        {
            
        }

        public int Count
        {
            get { return count; }
        }
        public int GetLength()
        {
            return count;
        }

        public bool IsEmpty()
        {
            return count == 0;
        }

        public void Clear()
        {
            count = 0;
            front = rear = -1;
        }

        public void Enqueue(T item)
        {
            if (count == data.Length)
            {
                Console.WriteLine("当前队列已满!");
            }
            else
            {
                if (rear == data.Length - 1)//如果队尾是最后一个数组的索引,则将新增元素放到队列第一个位置
                {
                    data[0] = item;
                    rear = 0;
                    count++;
                }
                else
                {
                    data[rear + 1] = item;
                    rear++;
                    count++;
                }
            }
        }

        public T Dequeue()
        {
            if (count > 0)
            {
                T temp = data[front + 1];
                front++;
                count--;
                return temp;
            }
            else
            {
                Console.WriteLine("队列为空,无法取得队首数据");
                return default(T);
            }
        }

        public T Peek()
        {
            T temp = data[front + 1];
            return temp;
        }
    }

链队列

队列的另外一种存储方式是链式存储,这样的队列称为链队列(Linked Queue)。同链栈一样,链队列通常用单链表来表示,它的实现是单链表的简化。由于链队列的操作只在一端进行,为了操作方便,把队头设在链表的头部,且不需要头结点。

链队列结点定义
public class Node<T>
    {
        private T data;
        private Node<T> next;

        public Node(T data)
        {
            this.data = data;
        }

        public T Data
        {
            get
            {
                return data;
            }
            set
            {
                data = value;
            }
        }

        public Node<T> Next
        {
            get { return next; }
            set { next = value; }
        }
    }
链队列实现
public class LinkedQueue<T>:IQueue<T>
    {
        private Node<T> front;//头节点
        private Node<T> rear;//尾节点
        private int count;//元素个数

        public LinkedQueue()
        {
            front = null;
            rear = null;
            count = 0;
        }

        public int Count
        {
            get { return count; }
        }
        public int GetLength()
        {
            return count;
        }

        public bool IsEmpty()
        {
            return count == 0;
        }

        public void Clear()
        {
            front = null;
            rear = null;
            count = 0;
        }

        public void Enqueue(T item)
        {
            Node<T> newNode = new Node<T>(item);
            if (count == 0)
            {
                front = newNode;
                rear = newNode;
                count = 1;
            }
            else
            {
                rear.Next = newNode;
                rear = newNode;
                count++;
            }
        }

        public T Dequeue()
        {
            if (count == 0)
            {
                Console.WriteLine("队列为空,无法出队");
                return default(T);
            }else if(count == 1)
            {
                T temp = front.Data;
                front = rear = null;
                count = 0;
                return temp;
            }
            else
            {
                T temp = front.Data;
                front = front.Next;
                count--;
                return temp;
            }
        }

        public T Peek()
        {
            if (front != null)
            {
                return front.Data;
            }
            else
            {
                return default(T);
            }
        }
    }

栈和队列的应用举例

编程判断一个字符串是否是回文。eg:"ABCDEDCBA"是回文。

算法思想:把第一个字符与最后一个字符相比较,第二个字符与倒数第二个字符比较。如果每次都相等,则为回文,反之则不是回文。因此,可以把字符序列分别入队列和栈,然后出个出队和出栈,并比较出队的字符与出栈的字符是否相等,若全部相等,则为回文。

            string str = Console.ReadLine();
            
            Stack<char> stack = new Stack<char>();
            Queue<char> queue = new Queue<char>();
            
            for (int i = 0; i < str.Length; i++)
            {
                stack.Push(str[i]);
                queue.Enqueue(str[i]);
            }

            bool isHui = true;
            while (stack.Count > 0)
            {
                if (stack.Pop() != queue.Dequeue())
                {
                    isHui = false;
                    break;
                }
            }
            Console.WriteLine("是否是回文字符串:" + isHui);
            Console.ReadKey();