数据结构与算法 Python (4)

队列Queue

队列是一种有次序的数据集合,其特征是:

新数据项的添加总发生在一端(通常称为“尾端rear”)

现存数据项的移除总发生在另一端(通常称为“首端”front)

队列中入口和出口分别只有一个,不允许数据项直接插入队中,也不允许从队列中间移除数据项

数据项加入队列时首先出现在队尾,随着队首数据项的移除,它逐渐靠近队首。

这种次序安排的原则称为FIFO(first-in first-out)先进先出

用Python中的List实现:

class queue():
    '''
    ADT Queue
    将第0位作为队首
    '''
    def __init__(self):
        '使用list实现队列'
        self.items = []

    def enqueue(self, item):
        '将数据项item添加到队尾'
        self.items.append(item)

    def dequeue(self):
        '将数据项从队首移除'
        return self.items.pop(0)

    def isEmpty(self):
        '判断队列是否为空'
        return self.items == []

    def size(self):
        '返回队列长度'
        return len(self.items)

    def tolist(self):
        '转化为列表'
        return self.itemsclass queue():

  • 注意:将第0位作为队首,那么添加数据的操作复杂度为 O ( 1 ) O(1) O(1),移除数据项的操作复杂度为 O ( n ) O(n) O(n)。将第0位作为队尾则反之。

双端队列Deque

双端队列是一种有次序的数据集,于队列类似,其两端可以成为首段和尾端。但deque中的双端都可以加入数据项,也可以移除。

从某种意义上来说,双端队列集成了栈和队列的能力。

双端队列并不具有内在的LIFO或FIFO的特性

用Python中的List实现:

class deque():
    '''
    ADT deque
    第0位为队首
    '''
    def __init__(self):
        '使用list实现双端队列'
        self.items = []

    def addFrout(self,item):
        '将item加入队首'
        self.items.insert(0,item)

    def addRear(self,item):
        '将item加入队尾'
        self.items.append(item)

    def removeFront(self):
        '移除队首数据项,并返回'
        return self.items.pop(0)

    def removeRear(self):
        '移除队尾数据项,并返回'
        return self.items.pop(-1)

    def isEmpty(self):
        return self.items == []

    def size(self):
        return len(self.items)

    def tolist(self):
        return self.items
  • 注意:第0位为队首,则队首添加或移除数据的操作复杂度为 O ( n ) O(n) O(n),队尾添加或删除数据的操作复杂度为 O ( 1 ) O(1) O(1)。如果第0位为队尾则反之。

双端队列的简单应用:回文词

回文词是正读反读都一样的词。比如12321,radar,madam,上海自来水来自海上,山东落花生花落东山……

利用双端队列很容易解决回文词问题。首先将回文词添加到双端队列,再从两端同时移除字符并判定是否相同,如不同则返回否,如果相同就继续移除并判定,直到deque中剩下0个或1个字符,返回是。

from custom_data_type import deque

def palchecker(string):
    chardeque = deque()

    for token in string:
        chardeque.addRear(token)

    stillEqual = True
    while stillEqual and chardeque.size() > 1:
        first = chardeque.removeFront()
        rear = chardeque.removeRear()
        if first != rear:
            stillEqual = False
        
    return stillEqual

链表

无序表UnorderdList

链表是一种数据项按照相对位置存放的数据集

Python中的列表在移除中间位置的一个数据项时,后面的数据要依次向前移动。因此这样的操作复杂度为 O ( n ) O(n) O(n)。这样的设计有Python自己的考虑

但是我们为了使移除任意数据项的操作复杂度为 O ( 1 ) O(1) O(1),可以使用链接表的方案实现List。

**虽然无序表要求保持数据项前后的相对位置,但不要求数据项必须存放在连续的存储空间。**我们可以使数据项之间建立链接指向,这样即使数据项不在连续的存储空间依然可以保持其前后的相对位置。

链表实现的最基本元素是节点Node。每个节点要包含两个信息:数据项和下一个节点的引用信息。

引用信息如果为None则没有下一个节点。

class Node:
    '''
    定义节点
    '''
    def __init__(self, initdata) -> None:
        self.data = initdata
        self.next = None

    def getData(self):
        return self.data

    def getNext(self):
        return self.next

    def setData(self, newdata):
        self.data = newdata

    def setNext(self, newnext):
        self.next = newnext

class UnorderdList:
    '''
    无序链表
    '''
    def __init__(self) -> None:
        self.head = None

    def add (self, item):
        temp = Node(item)
        temp.setNext(self.head)
        self.head = temp

    def size(self):
        current = self.head
        count = 0
        while current != None:
            count += 1
            current = current.getNext()

        return count

    def search(self, item):
        current = self.head 
        found = False
        while current != None and not found:
            if current.getData() == item:
                found = True
            else:
                current = current.getNext()
        
        return found

    def remove(self, item):
        current = self.head
        previous = None
        found = False
        while not found:
            if current.getData() == item:
                found = True
            else:
                previous = current
                current = current.getNext()

        if previous == None:
            self.head = current.getNext()
        else:
            previous.setNext(current.getNext())

有序表OrderdList

有序表与无序表类似,但是依据某种数据项的可比性质(比如数字的大小)来决定在列表中的位置。

由于的Python的可拓展性,对数据项的讨论不限于数字,可适用于所有定义了__gt__(富比较)方法的数据类型

有序表依然使用链表的实现方法,Node定义相同

class orderedList:
    '''
    有序表
    '''
    def __init__(self) -> None:
        self.head = Node

    def isEmpty(self):
        return self.head == None

    def size(self):
        current = self.head
        count = 0
        while current != None:
            count += 1
            current = current.getNext()

        return count

    def remove(self, item):
        current = self.head
        previous = None
        found = False
        while not found:
            if current.getData() == item:
                found = True
            else:
                previous = current
                current = current.getNext()

        if previous == None:
            self.head = current.getNext()
        else:
            previous.setNext(current.getNext())

    def search(self, item):
        current = self.head
        found = False
        stop = False
        while current != None and not found and not stop:
            if current.getData() == item:
                found = True
            else:
                if current.getData() > item:
                    stop = True
                else:
                    current = current.getNext()

        return found

    def add(self, item):
        current = self.head
        previous = None
        stop = False
        while current != None and not stop:
            if current.getData() > item:
                stop = True
            else :
                previous = current
                current = current.getNext()

        temp = Node(item)
        if previous == None:
            temp.setNext(self.head)
            self.head = temp
        else:
            temp.setNext(current)
            previous.setNext(temp)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值