Python数据结构与算法---双向链表和栈

1. 双向链表

单向链表只有一个方向,结点只有一个后继指针next指向后面的结点。而双向链表,顾名思义,它支持两个方向,每个结点不止有一个后继指针next指向后面的结点,还有一个前驱指针last指向前面的结点。

2. 双向链表的实现

'''
is_empty() 链表是否为空
length() 链表长度
travel() 遍历整个链表
append(item) 链表尾部添加元素
add(item) 链表头部添加元素
insert(pos, item) 指定位置添加元素
search(item) 查找节点是否存在
remove(item) 删除节点
'''

class Node(object):
    def __init__(self, item):
        self.item = item
        self.next = None
        self.last = None


class DoubleLinkList(object):
    def __init__(self, node=None):
        self.__head = node

    def is_empty(self):
        '''链表是否为空'''
        return self.__head == None

    def length(self):
        '''链表长度'''
        long = 0
        cur = self.__head
        while cur != None:
            long += 1
            cur = cur.next
        return long

    def travel(self):
        '''遍历整个链表'''
        cur = self.__head
        while cur != None:
            print(cur.item, end=' ')
            cur = cur.next
        print()

    def append(self, item):
        '''链表尾部添加元素'''
        node = Node(item)
        if self.is_empty():
            self.__head = node
        else:
            cur = self.__head
            while cur.next != None:
                cur = cur.next
            cur.next = node
            node.last = cur

    def add(self, item):
        '''链表头部添加元素'''
        node = Node(item)
        if self.is_empty():
            self.__head = node
        else:
            node.next = self.__head
            self.__head.last = node
            self.__head = node

    def insert(self, pos, item):
        '''指定位置添加元素'''
        if pos <= 0:
            self.add(item)
        elif pos >= self.length():
            self.append(item)
        else:
            node = Node(item)
            long = 0
            cur = self.__head
            while long < pos:
                cur = cur.next
                long += 1
            node.next = cur
            node.last = cur.last
            cur.last.next = node
            cur.last = node

    def search(self, item):
        '''查找节点是否存在'''
        if self.is_empty():
            return False
        else:
            cur = self.__head
            while cur != None:
                if cur.item ==item:
                    return True
                cur = cur.next
            return False

    def remove(self, item):
        '''删除节点'''
        if self.is_empty():
            return None
        elif self.__head.item == item:
            cur = self.__head
            if self.length() == 1:
                self.__head = None
                return None
            else:
                self.__head = cur.next
        else:
            cur = self.__head
            while cur.next != None:
                if cur.item == item:
                    cur.last.next = cur.next
                    cur.next.last = cur.last
                    return None
                cur = cur.next
            if cur.item == item:
                cur.last.next = None
                return None
            return None

3. 栈

关于“栈”,我有一个非常贴切的例子,就是一摞叠在一起的盘子。我们平时放盘子的时候,都是从下往上一个一个放;取的时候,我们也是从上往下一个一个地依次取,不能从中间任意抽出。后进者先出,先进者后出,这就是典型的“栈”结构。

在这里插入图片描述
从栈的操作特性上来看,栈是一种“操作受限”的线性表,只允许在一端插入和删除数据。

为什么还要用这个“操作受限”的“栈”呢?
:事实上,从功能上来说,链表确实可以替代栈,但你要知道,特定的数据结构是对特定场景的抽象,而且,数组或链表暴露了太多的操作接口,操作上的确灵活自由,但使用时就比较不可控,自然也就更容易出错。当某个数据集合只涉及在一端插入和删除数据,并且满足后进先出、先进后出的特性,我们就应该首选“栈”这种数据结构。

4. 栈的实现

用顺序表的方式实现栈

'''
Stack() 创建一个新的空栈
push(item) 添加一个新的元素item到栈顶
pop() 弹出栈顶元素
peek() 返回栈顶元素
is_empty() 判断栈是否为空
size() 返回栈的元素个数
'''


class Stack(object):
    def __init__(self):
        self.__items = []

    def is_empty(self):
        '''is_empty() 判断栈是否为空'''
        return self.__items == []

    def push(self, item):
        '''push(item) 添加一个新的元素item到栈顶'''
        self.__items.append(item)

    def pop(self):
        '''pop() 弹出栈顶元素'''
        self.pop()

    def peek(self):
        '''peek() 返回栈顶元素'''
        if self.is_empty():
            return None
        else:
            return self.__items[-1]

    def size(self):
        '''size() 返回栈的元素个数'''
        # i = 0
        # for item in self.__items:
        #     i += 1
        # return i
        return len(self.__items)

5. 小结

这堂课后,我学会了栈的实现,也对数据结构有了更加深刻的认识了。这节课的笔记写的不是那么的及时,以后还是要得更加努力地学习呀!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
大学生参加学科竞赛有着诸多好处,不仅有助于个人综合素质的提升,还能为未来职业发展奠定良好基础。以下是一些分析: 首先,学科竞赛是提高专业知识和技能水平的有效途径。通过参与竞赛,学生不仅能够深入学习相关专业知识,还能够接触到最新的科研成果和技术发展趋势。这有助于拓展学生的学科视野,使其对专业领域有更深刻的理解。在竞赛过程中,学生通常需要解决实际问题,这锻炼了他们独立思考和解决问题的能力。 其次,学科竞赛培养了学生的团队合作精神。许多竞赛项目需要团队协作来完成,这促使学生学会有效地与他人合作、协调分工。在团队合作中,学生们能够学到如何有效沟通、共同制定目标和分工合作,这对于日后进入职场具有重要意义。 此外,学科竞赛是提高学生综合能力的一种途径。竞赛项目通常会涉及到理论知识、实际操作和创新思维等多个方面,要求参赛者具备全面的素质。在竞赛过程中,学生不仅需要展现自己的专业知识,还需要具备创新意识和解决问题的能力。这种全面的综合能力培养对于未来从事各类职业都具有积极作用。 此外,学科竞赛可以为学生提供展示自我、树立信心的机会。通过比赛的舞台,学生有机会展现自己在专业领域的优势,得到他人的认可和赞誉。这对于培养学生的自信心和自我价值感非常重要,有助于他们更加积极主动地投入学习和未来的职业生涯。 最后,学科竞赛对于个人职业发展具有积极的助推作用。在竞赛中脱颖而出的学生通常能够引起企业、研究机构等用人单位的关注。获得竞赛奖项不仅可以作为个人履历的亮点,还可以为进入理想的工作岗位提供有力的支持。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值