栈和队列

概念:栈是一种特殊的线性表,保存一组元素的集合,插入和删除只能在尾部操作
其特点:
1.栈顶允许插入(入栈)和删除(出栈),另一部分为栈底
2.栈具有后进先出的特点

栈的创建
python中没有内置栈的实现,需要自己手动实现栈的概念,一般可以直接用list

实现:栈的底层其实就是list,通过list来实现栈

class Stack():

    def __init__(self):
        self.data = list()


    #len():返回栈中元素的个数,方法重写来实现
    def size(self):

        return len(self.data)

    #is_empty():判断栈是否为空
    def is_empty(self):

        return self.data == []

    #push():向栈中添加元素
    def push(self, data):
        self.data.append(data)

    #peek():获取栈顶元素:
    def peek(self):
        return self.data[len(self.data) - 1]

    #pop():删除栈顶元素,并返回
    def pop(self):
        return self.data.pop()

if __name__ == '__main__':
    stack = Stack()
    stack.push("a")
    stack.push("b")
    stack.push("c")

    length = stack.size()
    print(length)

    data = stack.pop()
    print(data)


    print(stack.peek())

    flag = stack.is_empty()
    print(flag)

栈常用方法:python中没有栈的内置方法,也就没有相关方法,不过根据栈的概念,我们可以用list中的方法实现栈的常用方法,参考list章节

队列

概念:同栈不同,python中的内置模块,主要有四种类型的队列:Queue, LifoQueue(后进先出队列), PriorityQueue,dequeue(双向队列)
Queue:先进先出队列,队尾插入,队首删除元素

  • Queue的创建:需要导queue这个包
#创建一个可扩容的队列
q = Queue()
#创建一个size为10的队列
q1 = Queue(10) 

#put():队列中插入元素
q.put("a")
q.put("b")

#get():获取队首元素,并从队列中删除此元素
q.get()
print(q.qsize())
while q.empty() == False:
    print("q中的元素是:", q.get())

#qsize():获取队列的size
print("q的size是:", q.qsize())
print("q1的size是: ", q1.qsize())

#q.empty():判断队列是否为空
print(q1.empty())

队列的常用方法

方法名 作用 返回值
put(item, block=True, timeout=None) 向队列中插入元素,在timeout范围内,若队列有空位则插入,不然超时报full异常,若后两个参数省略,则不会报异常 无返回值
put_nowait() 相当于put(),插入元素满了会报异常 无返回值
get(block=True, timeout=None) 删除队首元素,在指定time内,不然会报empt一场 返回删除的元素
Queue.get_nowait() 同get(),相当于timeout=False,若队列为空时会报异常 无返回
qsize() 获取队列的大小 返回队列大小
empty() 判断队列是否为空 返回bool
full() 判读队列是否满了 返回bool
task_done()
join()
  • put():插入元素,省略后两个参数,此时队列满了继续插入元素不会报异常
#创建一个size为3的队列
q = Queue(3)

q.put("a")
q.put("b")
q.put("c")

while not q.empty():
    print(q.get())
print(q.full())
#创建一个size为3的队列
q = Queue(3)

q.put("a")
q.put("b")
q.put("c")

#此时不会报异常
q.put("m")
image.png
  • put(item,black=Ture,timeout=None):队列满了,继续插入元素会报异常
#创建一个size为3的队列
q = Queue(3)

q.put("a")
q.put("b")
q.put("c")

q.put("d",block=True,timeout=2)
  • put_nowait():插入元素,插满了会报异常
q = Queue(3)

q.put("a")
q.put("b")
q.put("c")

q.put_nowait("d")
  • get():删除队首元素并返回
#创建一个size为3的队列
q = Queue(3)

q.put("a")
q.put("b")
q.put("c")

#不带参数的get()
q.get()
q.get()
q.get()
print(q.qsize())

#带参数的get()
q.get(block=True,timeout=2)

#get_nowait()
q.get_nowait()

*LifoQueue:后进先出队列,在队尾进行插入,在队尾进行删除

"""
LifoQueue():后进先出队列
"""
lq = LifoQueue()
lq.put("a")
lq.put("b")

while not lq.empty():
    print(lq.get())

PriorityQueue:优先级队列,按照优先级来取元素,元素以元祖形式插入,当两个元素优先级一致时,按照排序字段进行排序(从小到大),从而能快速获取最大值最小值

"""
PriorityQueue():优先级队列,按照元祖插入元素,元祖第一位为优先级
"""
pq = PriorityQueue()
pq.put((1, 9))
pq.put((1, 9, 2))
pq.put((1, 8))
pq.put((2, 0))

while not pq.empty():
    print(pq.get())

优先级比较不出,会报错(字典,不同类型的元素)

pq = PriorityQueue()
#优先级一样的元素,无法比较会报错
pq.put((1, {"k":1}))
pq.put((1,{"1":1}))
while not pq.empty():
    print(pq.get())
pq = PriorityQueue()
pq.put(('a', 9))
pq.put((1, 9, 2))
pq.put((1, 8))
pq.put((2, 0))
#
while not pq.empty():
    print(pq.get())

双向队列
与以上队列不同的是,双向队列是python的collections中的deque类,具有队列和栈的属性,可以从队头插入删除元素,也可以从队尾插入删除元素[拥有和list基本一样的方法]

  • 双向队列的创建
"""
双向队列deque:具有队列和栈的双属性,可以任意从队头队尾插入删除元素
"""
#[]可以省略,可见deque其实底层就是list,所以和list中某些方法的用法一致
dq = deque([])
dq1 = deque()

双向队列常用方法

方法名 作用 返回值
append(var) 插入元素 无返回值
appendleft(var) 向队头插入元素 无返回
extend([var1, var2,...]) 插入一组元素 无返回值
extendleft([var1, var2,...]) 向队头插入元素 无返回
insert(index, var) 向指定位置插入元素 无返回
remove(var) 删除指定var 无返回值
pop() 删除队尾元素 返回删除的元素
clear() 清空队列 无返回
popleft() 删除队头元素 返回删除的元素
remove(var) 删除指定元素 无返回值
copy() 拷贝当前队列 返回新的队列
count(var) 计算当前var的个数,不存在返回0 返回个数
reverse() 反转队列,在原队列上操作 无返回值
rotate(num) 将队尾num个元素取出并放置队头 无返回值
  • apend(var):插入元素,无返回值
dq = deque()
dq.append("a")
print(dq)
  • appendleft(var):向队列头插入元素,无返回
dq = deque()
dq.append("a")
dq.appendleft("x")
dq.extend(["aa","bb"])
print(dq)
  • extend([var1,var2,...]):插入一组元素,无返回值
dq = deque()
dq.append("a")
dq.extend(["aa","bb"])
print(dq)
  • extendleft([var1, var2,...]):向队伍头插入元素,无返回值
dq = deque()
dq.append("a")
dq.appendleft("x")
dq.extend(["aa","bb"])
dq.extendleft(["xs","zm"])
print(dq)

-insert(index, var):向指定位置插入元素,无返回

dq = deque()
dq.append("a")
dq.appendleft("x")
dq.extend(["aa","bb"])

dq.insert(1, "s")
print(dq)
  • remov(var):删除指定var,无返回值
dq = deque()
dq.append("a")
dq.appendleft("x")
dq.extend(["aa","bb"])
dq.extendleft(["xs","zm"])
print(dq)

dq.remove("a")
print(dq)
  • pop():删除队尾元素,返回删除的元素
dq = deque()
dq.append("a")
dq.appendleft("x")
dq.extend(["aa","bb"])
dq.extendleft(["xs","zm"])
re = dq.pop()
print(re)
  • popleft():删除队头元素
dq = deque()
dq.append("a")
dq.appendleft("x")
dq.extend(["aa","bb"])
dq.extendleft(["xs","zm"])
print(dq)
re = dq.popleft()
print(re)
  • remove(var):删除指定var,无返回值
dq = deque()
dq.append("a")
dq.appendleft("x")
dq.extend(["aa","bb"])
dq.extendleft(["xs","zm"])
print(dq)
dq.remove("xs")
print(dq)
  • clear():清空队列
dq = deque()
dq.append("a")
dq.appendleft("x")
dq.extend(["aa","bb"])
dq.extendleft(["xs","zm"])
dq.clear()
print(dq)
  • copy():拷贝队列,返回拷贝后的新队列
dq = deque()
dq.append("a")
dq.appendleft("x")
dq.extend(["aa","bb"])
dq.extendleft(["xs","zm"])
print("原队列:",dq)
print("原队列id:", id(dq))

dq1 = dq.copy()
print("拷贝的队列:", dq1)
print("拷贝后队列的id", id(dq1))
  • count(var):统计指定var的个数,若存在返回结果,反之,返回0
dq = deque()
dq.append("a")
dq.appendleft("x")
dq.extend(["aa","bb"])
dq.extendleft(["xs","zm"])
print(dq.count("aa"))

print(dq.count("b"))
  • reverse():在原队列基础上反转队列,不会创建新的队列
dq = deque()
dq.append("a")
dq.appendleft("x")
dq.extend(["aa","bb"])
dq.extendleft(["xs","zm"])

print(id(dq))
#reverse():反转队列
dq.reverse()
print(dq)
print(id(dq))
  • rotate(num):把队尾num个元素插入到队头
dq = deque()
dq.append("a")
dq.appendleft("x")
dq.extend(["aa","bb"])
dq.extendleft(["xs","zm"])


print("原队列", dq)

#rotate(num):轮转【相当于pop(),然后再appendleft()】
dq.rotate(4)
print("轮转后的队列", dq)

循环队列
非内置队列,将普通的队列首尾相连,head指向头,tail指向尾,每次插入一位元素tail都后移一位,每次删除元素head都后移

"""
循环队列:插入元素,tail++,删除元素,head++,
"""


class CircQueue():

    def __init__(self, maxsize):
        self.queue = [None] * maxsize
        self.maxsize = maxsize
        self.head = 0
        self.tail = 0
        self.cnt = 0

    #判断队列是否为空
    def is_empty(self):
        return self.cnt == 0

    #判断队列是否满
    def is_full(self):
        return self.cnt == self.maxsize

    #向队列中插入元素
    def push(self, val):
        if self.is_full():
            print("队列满了,无法插入元素")
            return

        if self.is_empty():
            self.queue[self.tail] = val
            self.cnt = 1

        else:
            self.tail = (self.tail + 1) % self.maxsize
            self.queue[self.tail] = val
            self.cnt += 1


    def pop(self):
        if self.is_empty():
            return " "

        val = self.queue[self.head]
        self.head = (self.head + 1) % self.maxsize
        self.cnt -= 1
        return val

    #清空队列
    def clear(self):
        if self.is_empty():
            return True

        self.head = 0
        self.tail = 0
        self.cnt = 0
        return True

    #计算当前队列长度
    def len(self):
        return self.cnt

    #获取列表中所有元素
    def get(self):
        if self.is_empty():
            return []
        l = []
        for i in range(self.cnt):
            index = (i + self.head) % self.maxsize
            l.append(self.queue[index])
        print(l)

if __name__ == '__main__':
    q = CircQueue(10)
    q.push("a")
    q.push("b")
    q.push("c")
    q.get()

    q.pop()
    q.get()

练习
最大k个数和最小k个数:
heaqp.nlargest(k, data)
heaqp.nsmallest(k, data)

import heaqp

nums = [1, 2, 3, 10, 9]

#最大3个数
ret1 = heaqp.nlargest(3, nums)
print(ret1)

#最小3个数
ret2 = heaqp.nsmallest(3, nums)
print(ret2)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容