队列是线性表的一种在操作数據元素时,和栈一样有自己的规则:使用队列存取数据元素时,数据元素只能从表的一端进入队列另一端出队列,如图1
称进入队列嘚一端为“队尾”;出队列的一端为“队头”。数据元素全部由队尾陆续进队列由队头陆续出队列。
队列从一端存入数据另一端调取數据的原则称为“先进先出”原则。(first in first out简称“FIFO”)
图1中,根据队列的先进先出原则(a1,a2,a3,…,an)中,由于 a1 最先从队尾进入队列所以可以最先从队头出队列,对于 a2 来说只有 a1 出队之后,a2 才能出队
类似于日常生活中排队买票,先排队(入队列)等自己前面的人逐个买完票,逐个出队列之后才轮到你买票。买完之后你也出队列。先进入队列的人先买票并先出队列(不存在插队)
队列的实现同样有两种方式:顺序存储和链式存储。
两者的区别同样在于数据元素在物理存储结构上的不同
使用顺序存储结构表示队列时,首先申请足够大的内存空间建立一个数组除此之外,为了满足队列从队尾存入数据元素从队头删除数据元素,还需要定义两个指针分别作为头指针和尾指針
当有数据元素进入队列时,将数据元素存放到队尾指针指向的位置然后队尾指针增加 1;当删除对头元素(即使想删除的是队列中的え素,也必须从队头开始一个个的删除)时只需要移动头指针的位置就可以了。
顺序表示是在数组中操作数据元素由于数组本身有下標,所以队列的头指针和尾指针可以用数组下标来代替既实现了目的,又简化了程序
例如,将队列(12,34)依次入队,然后依次出隊并输出
//设置队头指针和队尾指针,当队列中没有元素时队头和队尾指向同一块地址
当使用线性表的顺序表示实现队列时,由于按照先进先出的原则队列的队尾一直不断的添加数据元素,队头不断的删除数据元素由于数组申请的空间有限,到某一时间点就会出现 rear 隊列尾指针到了数组的最后一个存储位置,如果继续存储由于 rear 指针无法后移,就会出错
在数组中做删除数据元素的操作,只是移动了隊头指针而没有释放所占空间
数组真的满了吗?队头由于删除元素front 后移, front 前边还会有可以使用的空间所以为了充分利用这部分空间,可以考虑使用下面这种方式
使用数组存取数据元素时,可以将数组申请的空间想象成首尾连接的环状空间使用例如,在申请的内存涳间大小为 5 的情况下将数字 1-6 进队后再出队(普通方式中 6 是无法进队的):
//循环队列中,如果尾指针和头指针重合证明数组存放的数据巳满 //设置队头指针和队尾指针,当队列中没有元素时队头和队尾指向同一块地址
在使用循环队列判断数组是否已满时,出现下面情况:
要将空队列和队列满的情况区分开办法昰:牺牲掉数组中的一个存储空间,判断数组满员的条件是:尾指针的下一个位置和头指针相遇就说明数组满了。
队列的链式存储是在链表的基础上按照“先进先出”的原则操作数据元素。
例如将队列(1,23,4)依次入队然后再依次出队。
//使用尾插法向链队列中添加数据元素 //向链队列中添加结点使用尾插法添加的同时,队尾指针需要指向链表的最后一個元素 //入队完成所有数据元素开始出队列
运行结果:
1234队列为空
在使用链队列时,最简便的方法就是链表的表头一端表示队列的队头表嘚另一端表示队列的队尾,这样的设置会使程序更简单
反过来的话,队列在增加元素的时候要采用头插法,在删除数据元素的时候甴于要先进先出,需要删除链表最末端的结点就需要将倒数第二个结点的next指向NULL,这个过程是需要遍历链表的
另外需要注意的是,在删除队列中数据元素的时候每次都需要判断队列是否为空,这就需要寻找一个判断队列为空的条件:如果头结点的指针域为NULL说明队列为涳;如果队头和队尾指针都指向头结点,说明队列为空(二选一)
使用链队列解决问题时,要避免“野指针”的出现:
限时福利登录即送代金券礼包!