四、实现数组队列ArrayQueue
队列先进先出,和栈操作顺序相反,我们这里只实现入队,和出队操作,其他操作和栈一样。
package main
import "sync"
// 数组队列,先进先出
type ArrayQueue struct {
array []string //底层切片
size int //队列元素的数量
lock sync.Mutex //为了并发安全使用的锁
}
// 入队操作
func (queue *ArrayQueue) Add(v string) {
queue.lock.Lock()
defer queue.lock.Unlock()
//放入切片中,后进的元素放在数组最后面
queue.array = append(queue.array, v)
//队中元素数量+1
queue.size += 1
}
//直接将元素放在数组最后面即可,和栈一样,时间复杂度为:O(n)。
//出队操作
func (queue *ArrayQueue) Pop() string {
queue.lock.Lock()
queue.lock.Unlock()
//如果队列为空的话
if queue.size == 0 {
panic("队列已空")
}
//取出队列最前端的数据,但你要考了不后续元素补位问题
v := queue.array[0]
/*相当于处理方式1
直接原位进行移动,但缩容的后续的空间不会被释放
for i := 0; i < queue.size; i++ {
//从第一位开始进行数据移动操作
queue.array[i-1]=queue.array[i]
}
//并且原数组缩容
queue.array=queue.array[0:queue.size-1]
*/
//下面使用第二种开辟新数组进行操作
newArray := make([]string, queue.size-1, queue.size-1)
for i := 1; i < queue.size; i++ {
//从原数组的第一位进行开始数据移动
newArray[i-1] = queue.array[i]
}
queue.array = newArray
//然后队中元素数量-1
queue.size = queue.size - 1
return v
}
func main() {
}
注意:
出队,把数组的第一个元素的值返回,并对数据进行空间挪位,挪位有两种:
- 原地挪位,依次补位
queue.array[i-1] = queue.array[i]
,然后数组缩容:queue.array = queue.array[0 : queue.size-1]
,但是这样切片缩容的那部分内存空间不会释放。 - 创建新的数组,将老数组中除第一个元素以外的元素移动到新数组。
时间复杂度是:O(n)
。
五、实现链表队列LinkQueue
队列先进先出,和栈操作顺序相反,无非和上述实现方式不一样罢了
package main
import "sync"
//链表队列,先进先出
type LinkQueue struct {
root *LinkNode //链表起点
size int
lock sync.Mutex
}
type LinkNode struct {
next *LinkNode
Value string
}
// 入队操作
func (queue *LinkQueue) Add(v string) {
queue.lock.Lock()
defer queue.lock.Unlock()
//如果栈为空,就进行增加节点操作
if queue.root == nil {
queue.root = new(LinkNode)
queue.root.Value = v
} else {
//如果不为空,将新元素加入到我们的链表的末尾
//新节点的创建
newNode := new(LinkNode)
newNode.Value = v
// 一直遍历到链表尾部
nowNode := queue.root
for nowNode.next != nil {
newNode = nowNode.next
}
//然后将新节点放在链表末尾
nowNode.next = newNode
}
//队中元素数量+1
queue.size = queue.size + 1
}
//将元素放在链表的末尾,所以需要遍历链表,时间复杂度为:O(n)。
//出队操作
func (queue *LinkQueue) Remove() string {
queue.lock.Lock()
defer queue.lock.Unlock()
//队列元素已为空
if queue.size == 0 {
panic("队列为空")
}
//出队操作
topNode := queue.root
v := topNode.Value
//然后将顶部元素的后续链接连接上
queue.root = topNode.next
//并且队中元素数量-1
queue.size = queue.size - 1
return v
}
//链表第一个节点出队即可,时间复杂度为:O(1)。
func main() {
}