日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

数据结构 - 队列(图解+源码)

發(fā)布時間:2024/7/23 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据结构 - 队列(图解+源码) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

隊列

概念

隊列是一種特殊的線性表,特殊之處在于它遵循先入先出(FIFO)原則,只允許在表的前端(front)進行刪除操作,而在表的后端(rear)進行插入操作,和棧一樣,隊列是一種操作受限制的線性表。進行插入操作的端稱為隊尾,進行刪除操作的端稱為隊頭。

隊列區(qū)分

根據(jù)隊列的存儲方式不同可以分為順序存儲(數(shù)組)和鏈式存儲(鏈表),根據(jù)鏈表的形式又可以分為順隊列與循環(huán)隊列

順序隊列

順序隊列顧名思義就是一條路走到黑,front指向隊頭,rear指向隊尾,通過這兩個下標對隊列進行操作,如下圖所示:

每次在隊尾插入一個元素是,rear增1;每次在隊頭刪除一個元素時,front增1。隨著插入和刪除操作的進行,隊列元素的個數(shù)不斷變化,隊列所占的存儲空間也在為隊列結構所分配的連續(xù)空間中移動。當front=rear時,隊列中沒有任何元素,稱為空隊列。當rear增加到指向分配的連續(xù)空間之外時,隊列無法再插入新元素。

順序隊列實現(xiàn)

package queueimport "fmt"type Queue struct {maxSize intfront int // 隊列頭節(jié)點默認為節(jié)點的前一個rear int // 隊列尾節(jié)點queue []int }func NewQueue(maxSize int) *Queue {q := new(Queue)q.maxSize = maxSizeq.queue = make([]int, 0,maxSize)q.front = -1q.rear = -1return q }// Add 向隊列中添加元素 func (q *Queue) Add (val int) {if q.isFull() {fmt.Println("當前隊列已滿!")return}q.queue = append(q.queue, val)q.rear++return }// Get 從隊列中獲取元素 func (q *Queue) Get () int {if q.isEmpty() {return -1}q.front++return q.queue[q.front] }// Show 查看整個隊列元素 func (q *Queue) Show() []int{if q.isEmpty() {return []int{}}queues := make([]int, 0,q.maxSize)for i := q.front +1; i <= q.rear; i++{queues = append(queues, q.queue[i])}return queues }// 隊列是否滿了? func (q *Queue) isFull() bool {return q.rear == q.maxSize-1 }// 隊列是否為空 func (q *Queue) isEmpty() bool {return q.rear == q.front } `` ```bash package mainimport ("Queue/queue""fmt" )func main() {fmt.Println("add 添加元素")fmt.Println("get 獲取元素")fmt.Println("show 查看所有元素")fmt.Println("exit 退出程序")fmt.Printf("請輸入隊列長度:")var queueLen intfmt.Scanln(&queueLen)q := queue.NewQueue(queueLen)fmt.Println("隊列容積:", queueLen)for {var point stringfmt.Scanln(&point)switch point {case "add":fmt.Printf("輸入添加元素:")var val int_, err := fmt.Scanln(&val)if err != nil {continue}q.Add(val)case "get":getVal := q.Get()if getVal == -1{fmt.Println("隊列為空,請先添加元素^_^")}else{fmt.Println("獲取元素:", getVal)}case "show":vals := q.Show()if len(vals) == 0 {fmt.Println("隊列為空,請先添加元素^_^")}else{fmt.Println("隊列全部元素為:", vals)}case "exit":fmt.Println("bey~~")returndefault :fmt.Println("輸入有誤,請重新輸入-_-!!")}} }

運行效果

順序隊列中的溢出現(xiàn)象:

(1) "下溢"現(xiàn)象:當隊列為空時,做出隊運算產(chǎn)生的溢出現(xiàn)象。“下溢”是正常現(xiàn)象,常用作程序控制轉移的條件。
(2)"真上溢"現(xiàn)象:當隊列滿時,做進棧運算產(chǎn)生空間溢出的現(xiàn)象。“真上溢”是一種出錯狀態(tài),應設法避免。
(3)"假上溢"現(xiàn)象:由于入隊和出隊操作中,頭尾指針只增加不減小,致使被刪元素的空間永遠無法重新利用。當隊列中實際的元素個數(shù)遠遠小于向量空間的規(guī)模時,也可能由于尾指針已超越向量空間的上界而不能做入隊操作。該現(xiàn)象稱為"假上溢"現(xiàn)象。

可以發(fā)現(xiàn),當rear增加到指向分配的連續(xù)空間之外時,隊列無法再插入新元素,但這時往往還有大量可用空間未被占用,這些空間是已經(jīng)出隊的隊列元素曾經(jīng)占用過得存儲單元。既然這個問題這么明顯,肯定會有一個方案去解決。

循環(huán)隊列

像前面說的,順序隊列很容易就會造成空間的浪費,為了使隊列空間能重復使用,需要對順序隊列的使用方法稍加改進:

  • 無論插入或刪除,一旦rear指針增1或front指針增1 時超出了所分配的隊列空間,就讓它指向這片連續(xù)空間的起始位置。
  • 自己真從MaxSize-1增1變到0,可用取余運算rear%MaxSize和front%MaxSize來實現(xiàn)。
  • 這實際上是把隊列空間想象成一個環(huán)形空間,環(huán)形空間中的存儲單元循環(huán)使用,用這種方法管理的隊列也就稱為循環(huán)隊列。除了一些簡單應用之外,真正實用的隊列是循環(huán)隊列。
    在循環(huán)隊列中,當隊列為空時,有front=rear,而當所有隊列空間全占滿時,也有front=rear。為了區(qū)別這兩種情況,規(guī)定循環(huán)隊列最多只能有MaxSize-1個隊列元素,當循環(huán)隊列中只剩下一個空存儲單元時,隊列就已經(jīng)滿了。因此,隊列判空的條件時front=rear,而隊列判滿的條件時front=(rear+1)%MaxSize。
    循環(huán)的隊列的狀態(tài)如圖所示:

    循環(huán)隊列實現(xiàn)

    package circleQueueimport "fmt"type CircleQueue struct {front int //頭節(jié)點下標rear int //尾節(jié)點下標maxSize int //隊列容積queue []int }func NewCircleQueue(maxSize int) *CircleQueue {q := new(CircleQueue)q.maxSize = maxSize + 1 // 預留一個空位置做判斷q.front = 0q.rear = 0q.queue = make([]int, q.maxSize)return q }// Add 向隊列中添加元素 func (q *CircleQueue) Add(val int) {if q.isFull() {fmt.Println("當前隊列已滿!")return}q.queue[q.rear] = valq.rear = (q.rear + 1) % q.maxSizereturn }// Get 從隊列中獲取元素 func (q *CircleQueue) Get() int {if q.isEmpty() {return -1}defer func() {q.front = (q.front + 1) % q.maxSize}()return q.queue[q.front] }// Show 查看整個隊列元素 func (q *CircleQueue) Show() []int {if q.isEmpty() {return []int{}}// rear = 1 front = 3 1+4-3// rear = 3 front = 1 3+4-1queues := make([]int, 0, q.maxSize)for i := q.front; i < q.front + q.queueSize(); i++ {queues = append(queues, q.queue[i % q.maxSize])}return queues }// 隊列是否滿了? func (q *CircleQueue) isFull() bool {return (q.rear+1)%q.maxSize == q.front }// 隊列是否為空 func (q *CircleQueue) isEmpty() bool {return q.rear == q.front }// 獲取隊列元素個數(shù) func (q *CircleQueue) queueSize() int {return (q.rear + q.maxSize - q.front) % q.maxSize } package mainimport ("Queue/circleQueue""fmt" )func main() {fmt.Println("add 添加元素")fmt.Println("get 獲取元素")fmt.Println("show 查看所有元素")fmt.Println("exit 退出程序")fmt.Printf("請輸入隊列長度:")var queueLen intfmt.Scanln(&queueLen)q := circleQueue.NewCircleQueue(queueLen)fmt.Println("隊列容積:", queueLen)for {var point stringfmt.Scanln(&point)switch point {case "add":fmt.Printf("輸入添加元素:")var val int_, err := fmt.Scanln(&val)if err != nil {continue}q.Add(val)case "get":getVal := q.Get()if getVal == -1{fmt.Println("隊列為空,請先添加元素^_^")}else{fmt.Println("獲取元素:", getVal)}case "show":vals := q.Show()if len(vals) == 0 {fmt.Println("隊列為空,請先添加元素^_^")}else{fmt.Println("隊列全部元素為:", vals)}case "exit":fmt.Println("bey~~")returndefault :fmt.Println("輸入有誤,請重新輸入-_-!!")}}}

    運行效果

    由于最近在學習go語言,所以就用golang實現(xiàn)了^_^

    創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎

    總結

    以上是生活随笔為你收集整理的数据结构 - 队列(图解+源码)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。