github.com/qiuhoude/go-web@v0.0.0-20220223060959-ab545e78f20d/algorithm/datastructures/queue/circular_queue.go (about)

     1  package queue
     2  
     3  import (
     4  	"fmt"
     5  	"strconv"
     6  	"strings"
     7  )
     8  
     9  // 环形数组队列
    10  type CircularQueue struct {
    11  	data                 []interface{}
    12  	head, tail, capacity int
    13  }
    14  
    15  func NewCircularQueue(cap int) *CircularQueue {
    16  	rcap := cap + 1
    17  	return &CircularQueue{
    18  		data:     make([]interface{}, rcap, rcap),
    19  		head:     0,
    20  		tail:     0,
    21  		capacity: rcap,
    22  	}
    23  }
    24  
    25  func (q *CircularQueue) Dequeue() interface{} {
    26  	if q.IsEmpty() {
    27  		return nil
    28  	}
    29  	ret := q.data[q.head]
    30  	q.data[q.head] = nil
    31  	q.head = (q.head + 1) % q.capacity
    32  	return ret
    33  }
    34  
    35  func (q *CircularQueue) Enqueue(v interface{}) bool {
    36  	if (q.tail+1)%q.capacity == q.head { //满了
    37  		return false
    38  	}
    39  	q.data[q.tail] = v
    40  	q.tail = (q.tail + 1) % q.capacity
    41  	return true
    42  }
    43  
    44  func (q *CircularQueue) IsEmpty() bool {
    45  	return q.head == q.tail
    46  }
    47  
    48  func (q *CircularQueue) Len() int {
    49  	// 注意此时getSize的逻辑:
    50  	// 如果tail >= head,非常简单,队列中的元素个数就是tail - head
    51  	// 如果tail < head,说明我们的循环队列"循环"起来了,此时,队列中的元素个数为:
    52  	// tail  + capacity - head;tail  + capacity 表示绕过了环
    53  	if q.tail >= q.head {
    54  		return q.tail - q.head
    55  	} else {
    56  		return q.tail + q.capacity - q.head
    57  	}
    58  }
    59  
    60  func (q *CircularQueue) String() string {
    61  	var sb strings.Builder
    62  	sb.WriteString("head ")
    63  	for i := q.head; i%q.capacity != q.tail; i++ {
    64  		sb.WriteString(fmt.Sprintf("%v", q.data[i%q.capacity]))
    65  		if (i+1)%q.capacity != q.tail { // 非倒数第一个
    66  			sb.WriteString(",")
    67  		}
    68  	}
    69  	sb.WriteString(" tail size:" + strconv.Itoa(q.Len()))
    70  	sb.WriteString(", cap:" + strconv.Itoa(q.capacity))
    71  	return sb.String()
    72  }
    73  
    74  // 动态扩容和缩容
    75  func (q *CircularQueue) Poll() interface{} {
    76  	if q.IsEmpty() {
    77  		return nil
    78  	}
    79  	ret := q.data[q.head]
    80  	q.data[q.head] = nil
    81  	q.head = (q.head + 1) % q.capacity
    82  
    83  	len := q.Len()
    84  	// 长度等于容量的 1/4 进行缩容 容量的 1/2
    85  	if len == q.capacity/4 && q.capacity/2 != 0 {
    86  		q.resize(q.capacity / 2)
    87  	}
    88  	return ret
    89  }
    90  
    91  func (q *CircularQueue) Offer(v interface{}) bool {
    92  	if (q.tail+1)%q.capacity == q.head { // 满了
    93  		q.resize(2 * q.capacity) // 进行2倍的扩容
    94  	}
    95  	q.data[q.tail] = v
    96  	q.tail = (q.tail + 1) % q.capacity
    97  	return true
    98  }
    99  
   100  // 动态调整
   101  func (q *CircularQueue) resize(cap int) {
   102  	rcap := cap + 1
   103  	nData := make([]interface{}, rcap, rcap)
   104  	len := q.Len()
   105  	for i := 0; i < len; i++ {
   106  		nData[i] = q.data[(q.head+i)%q.capacity]
   107  	}
   108  	// 重新赋值
   109  	q.head = 0
   110  	q.tail = len
   111  	q.data = nData
   112  	q.capacity = rcap
   113  }