欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

golang實現(xiàn)循環(huán)隊列的示例代碼

 更新時間:2024年07月02日 09:57:51   作者:littleboy_webrtc  
循環(huán)隊列是一種使用固定大小的數(shù)組來實現(xiàn)隊列的數(shù)據(jù)結(jié)構(gòu),本文主要介紹了golang實現(xiàn)循環(huán)隊列的示例代碼,具有一定的參考價值,感興趣的可以了解一下

概要說明

循環(huán)隊列是一種使用固定大小的數(shù)組來實現(xiàn)隊列的數(shù)據(jù)結(jié)構(gòu),它通過循環(huán)的方式使用數(shù)組空間,具有以下好處:

  • 空間高效:循環(huán)隊列避免了使用鏈表實現(xiàn)隊列時可能存在的額外空間開銷,因為鏈表的每個節(jié)點都需要額外的存儲空間來保存指向下一個節(jié)點的指針。
  • 時間效率:在循環(huán)隊列中,入隊和出隊操作通??梢栽诔?shù)時間內(nèi)完成,即O(1)時間復雜度。這是因為不需要移動隊列中的其他元素。
  • 減少內(nèi)存分配:由于循環(huán)隊列使用固定大小的數(shù)組,它避免了動態(tài)分配內(nèi)存的需要,這在某些情況下可以減少內(nèi)存分配和回收的開銷。
  • 避免內(nèi)存碎片:固定大小的數(shù)組可以減少內(nèi)存碎片的產(chǎn)生,因為不需要為每個元素單獨分配內(nèi)存。
  • 實現(xiàn)簡單:循環(huán)隊列的實現(xiàn)相對簡單,只需要管理兩個指針(或索引)來跟蹤隊列的頭部和尾部。
  • 動態(tài)使用:循環(huán)隊列可以動態(tài)地使用數(shù)組空間,即使隊列滿了,也可以通過循環(huán)的方式繼續(xù)使用數(shù)組的未使用部分。
  • 適用于固定大小數(shù)據(jù)集:當數(shù)據(jù)集的大小已知且固定時,循環(huán)隊列可以非常高效地使用內(nèi)存和處理數(shù)據(jù)。
  • 減少錯誤:由于循環(huán)隊列的實現(xiàn)相對簡單,它減少了因復雜實現(xiàn)帶來的潛在錯誤。

避免假溢出是循環(huán)隊列設計中的一個重要問題。假溢出通常發(fā)生在循環(huán)隊列的頭部和尾部索引在數(shù)組中相遇時,即使數(shù)組中還有空間可以存放新元素。出現(xiàn)假溢出的原因,從根本上來說,是因為循環(huán)隊列的容量被錯誤地判斷為已滿。

隊列常見問題:假溢出

以下是幾種避免假溢出的策略:

  • 使用標志位:在循環(huán)隊列結(jié)構(gòu)中添加一個標志位來區(qū)分隊列是真正的滿還是假溢出。當隊列滿時,設置這個標志位;當隊列空時,清除這個標志位。
  • 使用計數(shù)器:維護一個計數(shù)器來記錄隊列中實際的元素數(shù)量。入隊時增加計數(shù)器,出隊時減少計數(shù)器。即使頭部和尾部索引相遇,計數(shù)器也能正確反映隊列的狀態(tài)。
  • 雙重索引:使用兩個索引來分別表示隊列的頭部和尾部,同時使用一個布爾值來區(qū)分隊列是滿還是空。當隊列滿時,尾部索引會等于頭部索引,但布爾值會標記隊列為滿。
  • 重新計算索引:在檢查隊列是否滿或空時,不要僅僅依賴于頭部和尾部索引的比較,而是重新計算它們在數(shù)組中的相對位置。
  • 使用額外的數(shù)組空間:在數(shù)組中預留一個額外的空間,這樣即使頭部和尾部索引相遇,也不會立即認為隊列滿了。這種方式犧牲了一點空間效率,但可以簡化邏輯。
  • 使用環(huán)形緩沖區(qū):在某些編程語言的庫中,環(huán)形緩沖區(qū)(ring buffer)是一種特殊的循環(huán)隊列,它通過使用上述一些策略來避免假溢出。
  • 動態(tài)擴容:雖然這并不直接解決假溢出問題,但通過動態(tài)擴容,可以在隊列達到容量上限時創(chuàng)建一個新的更大的數(shù)組,并將舊數(shù)組中的元素復制到新數(shù)組中。
  • 使用哨兵元素:在數(shù)組的末尾添加一個哨兵元素,這樣即使頭部和尾部索引相遇,哨兵元素也不會被誤認為是隊列中的有效元素。
  • 邏輯分離:在邏輯上將滿和空的狀態(tài)與頭部和尾部索引的相遇分離,通過額外的邏輯來確定隊列的真實狀態(tài)。
  • 使用狀態(tài)位圖:使用位圖來表示數(shù)組中哪些位置是被占用的,這樣可以通過位圖的狀態(tài)來判斷隊列是否滿或空。

避免假溢出的關鍵在于正確地維護隊列的狀態(tài)信息,確保在任何時候都能準確地判斷隊列是否真正滿了或者空了。在設計循環(huán)隊列時,應該根據(jù)具體的應用場景和性能要求來選擇最合適的策略。

在Go語言中實現(xiàn)循環(huán)隊列,我們需要定義一個循環(huán)隊列的數(shù)據(jù)結(jié)構(gòu),并實現(xiàn)其基本操作,包括初始化、入隊(Push)、出隊(Pop)、獲取隊列長度等。下面是一個簡單的循環(huán)隊列實現(xiàn)示例:

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

package QUEUE

import (
	"strings"
	"sync"
)

type CycleQueue struct {
	data  []interface{} //存儲空間
	front int           //前指針,前指針負責彈出數(shù)據(jù)移動
	rear  int           //尾指針,后指針負責添加數(shù)據(jù)移動
	cap   int           //設置切片最大容量
	mu    sync.RWMutex          // 添加互斥鎖
}

func NewCycleQueue(cap int) *CycleQueue {
	return &CycleQueue{
		data:  make([]interface{}, cap),
		cap:   cap,
		front: 0,
		rear:  0,
	}
}

// 入隊操作
// 判斷隊列是否隊滿,隊滿則不允許添加數(shù)據(jù)
func (q *CycleQueue) Push(data interface{}) bool {
	q.mu.Lock()
	defer q.mu.Unlock() // 確保在函數(shù)退出時釋放鎖

	//check queue is full
	if q.QueueLength() == q.cap { //隊列已滿時,不執(zhí)行入隊操作
		Log.Error("push err queue is full")
		return false
	}
	q.data[q.rear] = data         //將元素放入隊列尾部
	q.rear = (q.rear + 1) % q.cap //尾部元素指向下一個空間位置,取模運算保證了索引不越界(余數(shù)一定小于除數(shù))
	return true
}

// 出隊操作
// 需要考慮: 隊隊為空沒有數(shù)據(jù)返回了
func (q *CycleQueue) Pop() interface{} {
	q.mu.Lock()
	defer q.mu.Unlock()

	if q.rear == q.front {
		return nil
	}

	data := q.data[q.front]
	q.data[q.front] = nil // 使用nil來避免內(nèi)存泄露
	q.front = (q.front + 1) % q.cap
	return data
}

// 循環(huán)隊列長度計算,考慮哨兵空間
func (q *CycleQueue) QueueLength() int {
	if q.rear >= q.front {
		return q.rear - q.front
	}
	return q.cap - q.front + q.rear
}

func (q *CycleQueue) FindDataByRequestId(requestId string) interface{} {
	q.mu.Lock()
	defer q.mu.Unlock()

	// 計算隊列中的有效元素數(shù)量
	length := q.QueueLength()

	// 從front指針開始遍歷隊列
	index := q.front
	for i := 0; i < length; i++ {
		// 檢查當前元素是否包含requestId
		if data, ok := q.data[index].(string); ok && strings.Contains(data, requestId) {
			// 找到元素后,從隊列中移除
			q.RemoveAtIndex(index)
			return data
		}
		// 移動到下一個元素
		index = (index + 1) % q.cap
	}
	// 如果沒有找到,返回nil
	return nil
}

// 新增RemoveAtIndex方法,用于在循環(huán)隊列中移除指定索引的元素
func (q *CycleQueue) RemoveAtIndex(index int) {
	if index < 0 || index >= q.cap {
		return // 索引越界檢查
	}

	// 將index位置的元素復制到最后一個元素的位置
	copy(q.data[index:], q.data[index+1:q.rear])

	// 更新隊列的front和rear指針
	if index == q.rear { // 如果移除的是最后一個元素
		q.rear = index // rear指針向前移動
	} else if index < q.rear { // 如果移除的是中間的元素
		q.rear-- // rear指針向前移動
	}

	// 如果移除的是front指針前的元素
	if index < q.front {
		q.front = index // front指針向后移動
	}
}

循環(huán)隊列的應用

package server

import (
    "encoding/json"
    "strconv"
    "time"
)

//隊列通道
type Channel struct {
    queue                  *MeetGo.CycleQueue
}

//隊列參數(shù)項
type QueueItem struct {
    event    string
    msg      map[string]interface{}
    response *chan Response
}

//返回參數(shù)
type Response struct {
	err    interface{}
	result map[string]interface{}
}

var globalChannel *Channel


//創(chuàng)建隊列通道
func NewChannel() {
    channel.queue = QUEUE.NewCycleQueue(1000)
    go channel.handle()
    return
}

//處理隊列數(shù)據(jù)
func (channel *Channel) handle() {
    for {
        item := channel.queue.Pop()

        if item == nil {
            time.Sleep(40 * time.Millisecond)
            continue
        }
        channel.process(item)
        time.Sleep(1 * time.Millisecond)
    }
}

func (channel *Channel) process(inter interface{}) {
    item := inter.(QueueItem)
}

func (channel *Channel) PushSignal(item QueueItem) {
    Channel.queue.Push(item)
}

func (channel *Channel) onRequest(event string, msg map[string]interface{}) chan Response {
	response := make(chan Response, 1)
	item := QueueItem{
		event,
		msg,
		&response,
	}
	channel.PushSignal(item)
	return response

}

func main(){
    globalChannel = NewChannel()
    globalChannel.onRequset()
    println(response)
}

到此這篇關于golang實現(xiàn)循環(huán)隊列的示例代碼的文章就介紹到這了,更多相關golang 循環(huán)隊列內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家! 

相關文章

  • 解決golang http重定向失效的問題

    解決golang http重定向失效的問題

    這篇文章主要介紹了解決golang http重定向失效的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • 淺談Golang 切片(slice)擴容機制的原理

    淺談Golang 切片(slice)擴容機制的原理

    我們知道 Golang 切片在容量不足的情況下會進行擴容,擴容的原理是怎樣的呢,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • 詳解golang中模板的常用語法

    詳解golang中模板的常用語法

    這篇文章主要介紹了golang模板中的常用語法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-08-08
  • Go 語言中的select語句詳解及工作原理

    Go 語言中的select語句詳解及工作原理

    在Go語言中,select語句是用于處理多個通道(channel)操作的一種控制結(jié)構(gòu),它類似于 switch 語句,本文給大家介紹Go 語言中的select語句詳解及工作原理,感興趣的朋友一起看看吧
    2025-04-04
  • Mac GoLand打不開(閃退)也不報錯的解決方案

    Mac GoLand打不開(閃退)也不報錯的解決方案

    這篇文章主要介紹了Mac GoLand打不開(閃退)也不報錯的解決方案,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • Go單元測試對GORM進行Mock測試

    Go單元測試對GORM進行Mock測試

    這篇文章主要為大家介紹了Go單元測試對GORM進行Mock測試用例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-06-06
  • golang 定時任務方面time.Sleep和time.Tick的優(yōu)劣對比分析

    golang 定時任務方面time.Sleep和time.Tick的優(yōu)劣對比分析

    這篇文章主要介紹了golang 定時任務方面time.Sleep和time.Tick的優(yōu)劣對比分析,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-05-05
  • 詳解用Go語言實現(xiàn)工廠模式(Golang經(jīng)典編程案例)

    詳解用Go語言實現(xiàn)工廠模式(Golang經(jīng)典編程案例)

    這篇文章主要介紹了詳解用Go語言實現(xiàn)工廠模式(Golang經(jīng)典編程案例),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-04-04
  • Go語言中節(jié)省內(nèi)存技巧方法示例

    Go語言中節(jié)省內(nèi)存技巧方法示例

    這篇文章主要為大家介紹了Go語言中節(jié)省內(nèi)存技巧方法示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-01-01
  • Go?Web實戰(zhàn)之創(chuàng)建項目及增加日志功能

    Go?Web實戰(zhàn)之創(chuàng)建項目及增加日志功能

    這篇文章主要為大家詳細介紹了Go?Web項目中如何實現(xiàn)創(chuàng)建項目及增加日志功能,文中的示例代碼講解詳細,感興趣的小伙伴可以了解一下
    2022-11-11

最新評論