数据结构(四)——队列

一:队列的概述

队列是一个先进先出的线性表结构,在一端进行插入操作,另一段进行删除操作。例如我们平时打客服电话会忙线(客户数总是多于客服数,当客服空下来时,会先接通最先等待的客户的电话)、使用键盘进行各种数字字母的输入(输入god,也会输出god,而不是dog)、现实生活中的排队(先排队的先出队,后排队的后出队),我们把允许插入的一端称为队尾,允许删除的一段称为队头,插入操作称为入队,删除操作称为出队
定义说队列是一种线性表,它其实是一种特殊的线性表,它限制了插入、删除的位置


二:队列的顺序存储结构

用一段地址连续的存储单元依次存储队列中的数据元素
按照正常的顺序存储结构的话,在插入数据时,时间复杂度是O(1),但是在删除数据时,队列中所有元素都需要向前移动保证下标为0的位置不为空,所以时间复杂度是O(n),其实我们可以不限制队头元素必须是下标为0的位置,我们可以定义两个变量去指向不同位置,front变量指向队头元素,rear变量指向队尾元素的下一个位置,当删除一个元素时,front++,当插入一个元素时,rear++,当front=rear时队列为空,当rear等于存储队列中元素数组的长度时,表示队列已满,但是当数组的最后一个元素被占用时,rear会指向数组存储空间外的位置,发生数组越界的错误,但其实数组的前端是有空位置的,这种现象叫做"假溢出"

这样对队列的顺序存储结构进行了细微优化后,在读、取,插入,删除数据时,时间复杂度都是O(1),但是会发生假溢出现象,造成空间的浪费于是引出了循环队列,队尾指针溢出的话就再次指向下标为0的位置,我们把这种头尾相连的队列顺序存储结构称为循环队列
但是在循环队列中当front=rear时,到底为空队列还是队列已满呢?我们可以使用count变量进行计数,当front=rear并且count=0时队列为空,当front=rear并且count=存储队列中元素数组的长度时队列为满


三:队列的链式存储结构

引言:对于队列的顺序存储结构,在插入数据时,时间复杂度是O(1),但是在删除数据时,时间复杂度是O(n),进行了细微优化后的循环队列虽然在插入、删除数据的时间复杂度都是O(1),但是又面临着顺序存储结构的通病——需要预先分配内存空间,所以引出了队列的链式存储结构(链队列)

因为队列只能在队头进行删除操作,队尾进行插入操作,所以需要两个指针引用,一个是队头指针,指向链队列的队头结点,一个是队尾指针,指向链队列的队尾结点。当添加元素时,若当前队列中没有元素则添加的结点既是队头结点也是队尾结点,若有元素则让队尾指针的后继指向新添加的结点即可。当删除元素时,若当前元素个数为1时,则出队后队头、队尾结点都为空,若当前元素个数不为1时,则让队头指向当前队头的下一个结点即可


四:实现队列的顺序存储结构(顺序队列)

using System;

//顺序队列类
public class Queue<T>
{
    //存储顺序队列中元素的数组
    private T[] array;

    //顺序队列中元素的个数
    public int Count
    {
        get
        {
            return rear - front;
        }
    }

    //队头元素的下标
    private int front;

    //队尾元素的下标
    private int rear;

    //构造器初始化
    public Queue()
    {
        array = new T[0];
        front = 0;
        rear = 0;
    }
    public Queue(int size)
    {
        array = new T[size];
        front = 0;
        rear = 0;
    }

    //判断队列是否为空
    public bool IsEmpty()
    {
        return front == rear;
    }

    //判断队列是否已满
    private bool IsFull()
    {
        return rear == array.Length;
    }

    //清空顺序队列
    public void Clear()
    {
        front = 0;
        rear = 0;
    }

    //入队
    public void EnQueue(T item)
    {
        if (!IsFull())
        {
            array[rear] = item;
            rear++;
        }
        else
        {
            throw new Exception("队列当前已满");
        }
    }

    //出队
    public T DeQueue()
    {
        if (!IsEmpty())
        {
            T temp = array[front];
            front++;
            return temp;
        }
        else
        {
            throw new Exception("队列当前为空");
        }
    }

    //得到队头元素
    public T Peek()
    {
        if (!IsEmpty())
        {
            return array[front];
        }
        else
        {
            throw new Exception("队列当前为空");
        }
    }
}

class Program
{
    //*****进行测试*****
    static void Main(string[] args)
    {
        Queue<int> myQueue = new Queue<int>(10);
        myQueue.EnQueue(1);
        myQueue.EnQueue(2);
        myQueue.DeQueue();
        myQueue.Peek();
    }
}

五:实现队列的顺序存储结构的优化(循环队列)

using System;

//循环队列类
public class Queue<T>
{
    //存储循环队列中元素的数组
    private T[] array;

    //循环队列中元素的个数
    private int count;
    public int Count
    {
        get
        {
            return count;
        }
    }

    //队头元素的下标
    private int front;

    //队尾元素的下标
    private int rear;

    //构造器初始化
    public Queue()
    {
        array = new T[0];
        front = 0;
        rear = 0;
    }
    public Queue(int size)
    {
        array = new T[size];
        front = 0;
        rear = 0;
    }

    //判断队列是否为空
    public bool IsEmpty()
    {
        return front == rear && count == 0;
    }

    //判断队列是否已满
    private bool IsFull()
    {
        return front == rear && count == array.Length;
    }

    //清空循环队列
    public void Clear()
    {
        count = 0;
        front = 0;
        rear = 0;
    }

    //入队
    public void EnQueue(T item)
    {
        if (!IsFull())
        {
            array[rear] = item;
            rear = (rear + 1) % array.Length;
            count++;
        }
        else
        {
            throw new Exception("队列当前已满");
        }
    }

    //出队
    public T DeQueue()
    {
        if (!IsEmpty())
        {
            T temp = array[front];
            front = (front + 1) % array.Length;
            count--;
            return temp;
        }
        else
        {
            throw new Exception("队列当前为空");
        }
    }

    //得到队头元素
    public T Peek()
    {
        if (!IsEmpty())
        {
            return array[front];
        }
        else
        {
            throw new Exception("队列当前为空");
        }
    }
}

class Program
{
    //*****进行测试*****
    static void Main(string[] args)
    {
        Queue<int> myQueue = new Queue<int>(10);
        myQueue.EnQueue(1);
        myQueue.EnQueue(2);
        myQueue.DeQueue();
        myQueue.Peek();
    }
}

六:实现队列的链式存储结构(链队列)

using System;

//结点类
public class Node<T>
{
    //数据域
    public T Data { get; set; }

    //指针域
    public Node<T> Next { get; set; }

    //构造器初始化
    public Node()
    {
        this.Data = default(T);
        Next = null;
    }
    public Node(T value)
    {
        this.Data = value;
        Next = null;
    }
    public Node(T value, Node<T> next)
    {
        this.Data = value;
        this.Next = next;
    }
    public Node(Node<T> next)
    {
        this.Next = next;
    }
}
//链队列类
public class Queue<T>
{
    //队头指针
    private Node<T> front;
    //队尾指针
    private Node<T> real;

    //链队列中元素的个数
    private int count;
    public int Count
    {
        get
        {
            return count;
        }
    }

    //构造器初始化
    public Queue()
    {
        front = null;
        real = null;
        count = 0;
    }

    //判断队列是否为空
    public bool IsEmpty()
    {
        return count == 0;
    }

    //清空顺序队列
    public void Clear()
    {
        front = null;
        real = null;
        count = 0;
    }

    //入队
    public void EnQueue(T item)
    {
        Node<T> addNode = new Node<T>(item);
        if (real == null)
        {
            real = addNode;
            front = addNode;
        }
        else
        {
            real.Next = addNode;
            real = addNode;
        }
        count++;
    }

    //出队
    public T DeQueue()
    {
        if (!IsEmpty())
        {
            Node<T> temp = front;
            if (count == 1)
            {
                front = real = null;
            }
            else
            {
                front = front.Next;
            }
            count--;
            return temp.Data;
        }
        else
        {
            throw new Exception("队列当前为空");
        }
    }

    //得到队头元素
    public T Peek()
    {
        if (!IsEmpty())
        {
            return front.Data;
        }
        else
        {
            throw new Exception("队列当前为空");
        }
    }
}

class Program
{
    //*****进行测试*****
    static void Main(string[] args)
    {
        Queue<int> myQueue = new Queue<int>(10);
        myQueue.EnQueue(1);
        myQueue.EnQueue(2);
        myQueue.DeQueue();
        myQueue.Peek();
    }
}
发布了127 篇原创文章 · 获赞 278 · 访问量 24万+

猜你喜欢

转载自blog.csdn.net/LLLLL__/article/details/100835477