栈和队列

概念:栈是一种特殊的线性表,保存一组元素的集合,插入和删除只能在尾部操作
其特点:
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)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,591评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,448评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,823评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,204评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,228评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,190评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,078评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,923评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,334评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,550评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,727评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,428评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,022评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,672评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,826评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,734评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,619评论 2 354

推荐阅读更多精彩内容