隊列
- 隊列介紹
- 隊列是一個有序列表,可以使用
數組
或者鏈表
來實現 - 遵循先入先出的原則(先存入隊列的數據,要先取出。後存入的要後取出)
- 樣例圖(使用
數組模型
示意圖)
隊列本身是有序列表,如上面的圖之中maxSize是該隊列的最大容量,開頭,結尾分別記錄隊列前後端的下標(類似索引),開頭會隨着數據的輸出而改變,結尾則是隨着數據的輸入而改變。
小結:
: 1.隊列是有序隊列
: 2.開始初始化爲-1,表示隊列的頭,但是約定不包含頭元素,即指向隊列的第一個元素的前一個位置
: 3.結尾初始化爲-1,表示隊列的尾,但是包含最後這個元素,即指向隊列尾部
: 4.判斷隊列空,開始 == 結尾 表示空
: 5.判斷隊列滿,結尾 == maxSize-1
向隊列加入數據的時候會有兩個步驟
1 將結尾向後移:結尾+1(這個過程要先判斷開始結尾是否相等,如果相等隊列爲空)
2 判斷結尾跟maxSize-1:如果結尾小於maxSize-1,則將數據放入到結尾所指向的數組元素中;否則數據無法存入,即結尾 == maxSize(隊列滿了,已達到最大值)
代碼(沒優化前)
import scala.io.StdIn
object test01 {
def main(args: Array[String]): Unit = {
val queue = new addDateDemo(3)
// 菜單演示
var key = ""
while (true) {
println()
println("請選擇菜單")
println("show : 顯示隊列")
println("add : 添加數據")
println("get : 獲取數據")
println("peek(偷看): 查看頭元素值")
println("exit : 退出程序")
key = StdIn.readLine()
key match {
case "show" => queue.show()
case "add" =>
println("請輸入一個數")
val num: Int = StdIn.readInt()
queue.addDate(num)
case "get" =>
// 獲取返回值
val res: Any = queue.getDates()
// 判斷返回值是否爲空
if (res.isInstanceOf[Exception]){
println(res.asInstanceOf[Exception].getMessage)
}else{
// 查看隊列元素信息
printf("隊列取出的值=%d",res)
}
case "peek" =>
// 獲取返回值
val res: Any = queue.peek()
// 判斷返回值是否爲空
if (res.isInstanceOf[Exception]){
println(res.asInstanceOf[Exception].getMessage)
}else{
// 查看頭元素
printf("隊列當前頭元素的值=%d",res)
}
}
}
}
}
// 編寫一個數據結構的基本思路 創建-遍歷(查看)-修改-刪除
class addDateDemo(arrMaxSize: Int) {
// 指定隊列大小
val maxSize = arrMaxSize
// 隊列中數據,存放在數組,即數組模擬隊列
val arr = new Array[Int](maxSize)
// 初始化開始
var start = -1
// 初始化結尾
var end = -1
// 判斷隊列是否滿了
def isFull(): Boolean = {
end == maxSize - 1
}
// 判斷隊列是否爲空
def isEmpty(): Boolean = {
start == end
}
// 查看隊列的頭元素,但是不取出
def peek(): Any ={
if (isEmpty()) {
return new Exception("隊列爲空,什麼都沒有")
}
return arr(start+1) // start不進行+=1
}
// 相隊列中添加數據 num
def addDate(num: Int): Unit = {
// 如果已經滿了就不能添加進去了
if (isFull()) {
println("隊列已滿,無法加入")
return
}
// 隊列沒滿 ,將end後移
end += 1
arr(end) = num
}
// 遍歷(顯示)
def show(): Unit = {
// 先判斷隊列是否爲空
if (isEmpty()) {
println("什麼都沒有")
println()
return
}
// 如果不爲空,遍歷打印結果
println("隊列數據:")
for (i <- start + 1 to end) {
printf("arr(%d)=%d \t", i, arr(i))
}
println()
}
// 從隊列中取數據, 可能取到數據,可能取不到數據
def getDates(): Any = {
if (isEmpty()) {
return new Exception("隊列爲空,沒有數據")
}
// 將start後移
// 取數據不是把數據刪了,而是不讓我們訪問到了
// 又因爲隊列前進先出,數據必須從第一個元素(也就是start)開始取,所以+1就不會再看到之前的數據
start += 1
return arr(start)
}
}
效果圖:
數組模擬環形隊列
- 對前面的數組模擬隊列的優化,充分利用數組。因此將數組看做是一個環形的。(通過取模的方式來實現即可)
- 1.將start初始化爲0,start指向隊列的第一個元素
- 2.將end初始化爲0,end指向的是隊列的最後一個元素的後一個位置
- 3.通過%將隊列當做環形,判斷隊列是否爲空通過 start == end
- 4.判斷隊列元素滿的條件是(end+1)%maxSize=start, +1的原因的預留了一個空間作爲約定
代碼(優化後)
import scala.io.StdIn
object test02 {
def main(args: Array[String]): Unit = {
val queue = new addDateDemo2(4)
// 菜單演示
var key = ""
while (true) {
println()
println("請選擇菜單")
println("show : 顯示隊列")
println("add : 添加數據")
println("get : 獲取數據")
println("peek(偷看): 查看頭元素值")
println("exit : 退出程序")
key = StdIn.readLine()
key match {
case "show" => queue.show()
case "add" =>
println("請輸入一個數")
val num: Int = StdIn.readInt()
queue.addDate(num)
case "get" =>
// 獲取返回值
val res: Any = queue.getDates()
// 判斷返回值是否爲空
if (res.isInstanceOf[Exception]) {
println(res.asInstanceOf[Exception].getMessage)
} else {
// 查看隊列元素信息
printf("隊列取出的值=%d", res)
}
case "peek" =>
// 獲取返回值
val res: Any = queue.peek()
// 判斷返回值是否爲空
if (res.isInstanceOf[Exception]) {
println(res.asInstanceOf[Exception].getMessage)
} else {
// 查看頭元素
printf("隊列當前頭元素的值=%d", res)
}
}
}
}
}
// 編寫一個數據結構的基本思路 創建-遍歷(查看)-修改-刪除
class addDateDemo2(arrMaxSize: Int) {
// 指定隊列大小
val maxSize = arrMaxSize
// 隊列中數據,存放在數組,即數組模擬隊列
val arr = new Array[Int](maxSize)
// 初始化開始
var start = 0
// 初始化結尾
var end = 0
// 判斷隊列是否滿了
def isFull(): Boolean = {
(end + 1) % maxSize == start
}
// 判斷隊列是否爲空
def isEmpty(): Boolean = {
start == end
}
// 查看隊列的頭元素,但是不取出
def peek(): Any = {
if (isEmpty()) {
return new Exception("隊列爲空,什麼都沒有")
}
return arr(start) // start不進行+=1
}
// 相隊列中添加數據 num
def addDate(num: Int): Unit = {
// 如果已經滿了就不能添加進去了
if (isFull()) {
println("隊列已滿,無法加入")
return
}
arr(end) = num
// 隊列沒滿 ,將end後移
end = (end + 1) % maxSize
}
// 從隊列中取數據, 可能取到數據,可能取不到數據
def getDates(): Any = {
if (isEmpty()) {
return new Exception("隊列爲空,沒有數據")
}
// 因爲start指向隊列的第一個元素
// 先將數據保存到臨時變量中
val res: Int = arr(start)
// start 後移
start = (start + 1) % maxSize
return res
}
// 遍歷(顯示)
// 從start開始打印,打印多少個元素就可以了,所以需要統計出該隊列有多少個有效元素
def show(): Unit = {
// 先判斷隊列是否爲空
if (isEmpty()) {
println("什麼都沒有")
println()
return
}
// 使用取模的方式
// 如果不爲空,遍歷打印結果
println("隊列數據:")
for (elem <- start until start + size()) {
printf("arr(%d)=%d \t", (elem % maxSize), arr(elem % maxSize))
}
}
// 編寫一個方法,統計當前有多少個元素
def size(): Int = {
return (end + maxSize - start) % maxSize
}
}
效果圖: