通过数据结构学习Python-手写链表实现队列、栈、双端队列、双向链表

382 阅读4分钟

What?

提升技能时规划了学习Python这一项,于是花了一周的时间通过看视频从头学习了Python。

视频是在油管上一个Programming with Mosh作者录制的《Python Tutorial - Python Full Course for Beginners》,每天看一个小时左右,一周看完边看边敲代码学习。个人觉得视频不错,适合初学者,全英文不过基本都能听懂。想看的可以去油管找一下或者私信我也可以。

Why?

学习完Python之后,只能掌握基本的语法,甚至一些语法规则容易和Java混乱,比如泛型的使用Java使用的是,而Python使用的是(object),或者for循环遍历Java使用的是for i : arrays,而Python使用的是for i in range(等容易混乱的点。

那么为什么用数据结构的实现来巩固呢?

  • 经常使用:数据结构在各大语言中都是离不开的开发实现,数组、栈、队列、链表、哈希等平时都会直接使用,因此针对数据结构联系可以增加平时Python开发的便利。
  • 算法:刷Leetcode时Python也是经常使用的语言,并且刷Leetcode时很多题目都是基于链表、栈、队列进行实现的,掌握基本数据结构也有利于刷LeetCode
  • 个人习惯:大学学习Java语言时不咋理解语言的含义,我就用最笨的办法把数据结构书上的算法实现都照着敲一遍,敲的过程中理解各种数据结构为什么是这样实现,因此现在学习Python也使用相同的套路。

How?

由于个人对链表有很深的芥蒂,各种next、pre总是混乱,因此一下所有的数据结构实现都是基于链表实现的。

单向链表的实现

# 链表节点类
class Node:
    item = None
    next = None

    def __init__(self, item):
        self.item = item
        self.next = None


# 链表类
class List(object):
    def __init__(self):
        self.first = Node

    def is_empty(self):
        return self.first is None

    def size(self):
        size = 0
        cur = self.first
        while cur is not None:
            size = size + 1
            cur = cur.next
        return size

    # 头部添加元素
    def head_push(self, item):
        node = Node(item)
        node.next = self.first
        self.first = node

    # 尾部添加元素
    def tail_push(self, item):
        node = Node(item)
        if self.is_empty():
            self.first = node
        else:
            # 遍历找尾部
            cur = self.first
            while cur.next.item is not None:
                cur = cur.next
            cur.next = node

    # 移除指定元素
    def remove(self, item):
        if self.is_empty():
            print("exception")
        else:
            cur = self.first
            pre = None
            if self.first.item == item:
                self.first = self.first.next
            else:
                while cur is not None:
                    if cur.item == item:
                        pre.next = cur.next
                        break
                    else:
                        pre = cur
                        cur = cur.next
#测试用例
if __name__ == '__main__':
    list = List()
    list.head_push(1)
    list.head_push(3)
    list.head_push(5)
    list.head_push(7)
    list.head_push(9)
    list.head_push(8)
    list.tail_push(2)
    list.remove(2)
    print(list.size())

双向链表的实现

class Node:
    item = None
    # 前指针
    pre = None
    # 后指针
    next = None

    def __init__(self, item):
        self.item = item
        self.pre = None
        self.next = None


class DoubleList(object):

    def __init__(self):
        self.head = Node

    # 从头部插入元素
    def head_push(self, item):
        node = Node(item)
        if self.head is None:
            self.head = node
        else:
            node.next = self.head
            self.head.pre = node
            self.head = node

    # 从尾部插入元素
    def tail_push(self, item):
        node = Node(item)
        if self.head is None:
            self.head = node
        else:
            # 遍历找到尾部元素
            cur = self.head
            while cur.next.item is not None:
                cur = cur.next
            cur.next = node
            node.pre = cur


    def size(self):
        size = 0
        cur = self.head
        while cur.next is not None:
            size = size + 1
            cur = cur.next
        return size

    # 移除指定元素
    def remove(self, item):
        if self.head is None:
            print("head is null")
        else:
            cur = self.head
            while cur.next.item is not None:
                if item == cur.item:
                    cur.pre.next = cur.next
                    cur.next.pre = cur.pre
                    break
                else:
                    cur = cur.next


if __name__ == '__main__':
    double = DoubleList()
    double.head_push(1)
    double.head_push(2)
    double.head_push(3)
    double.tail_push(4)
    double.remove(1)
    print(double.size())

栈的实现-通过链表实现

class Node(object):
    next = None
    item = None

    def __init__(self, item):
        self.item = item
        self.next = None
        
        

class Stack(object):
    def __init__(self):
        self.head = Node
        self.size = 0

    def is_empty(self):
        return self.head is None
    # 从栈顶入栈
    def push(self, item):
        old = self.head
        new_node = Node(item)
        new_node.next = old
        self.head = new_node
        self.size = self.size + 1
        
    # 从栈顶出栈
    def pop(self):
        old = self.head.item
        self.head = self.head.next
        self.size = self.size - 1
        return old
    
    # 反转栈
    def reverse(self):
        first = self.head  # 3-2-1
        reverse_node = None
        while first.item is not None:
            second = first.next  # 2-1
            first.next = reverse_node
            reverse_node = first  # 2-1
            first = second
        return reverse_node


if __name__ == '__main__':
    stack = Stack()
    stack.push(1)
    stack.push(2)
    stack.push(3)
    # for i in range(0, stack.size):
    reverse_stack = stack.reverse(stack.head)
    print(stack.size)

队列的实现-通过链表实现

class Node:
    next = None
    item = None

    def __init__(self, item):
        self.item = item
        self.next = None


class Queue(object):

    def __init__(self):
        self.size = 0
        self.first = None
        self.last = None

    def is_empty(self):
        return self.first is None

    # 从队尾入队
    def enqueue(self, item):
        old = self.last
        self.last = Node(item)
        self.last.next = None
        if self.is_empty():
            self.first = self.last
        else:
            old.next = self.last
        self.size = self.size + 1
        
    # 从队头出队
    def dequeue(self):
        item = self.first
        self.first = self.first.next
        if self.is_empty():
            self.last = None
        self.size = self.size - 1
        return item



if __name__ == '__main__':
    queue = Queue()
    queue.enqueue(1)
    queue.enqueue(2)
    queue.enqueue(3)
    queue.dequeue()
    print(queue.size)

双端队列的实现- 通过链表实现

class Node:
    item = None
    next = None

    def __init__(self, item):
        self.item = item
        self.next = None


class Deque(object):

    def __init__(self):
        self.first = Node
        self.last = None

    # 队头添加元素
    def head_push(self, item):
        node = Node(item)
        if self.first.item is None:
            self.first = node
            self.last = node
        else:
            node.next = self.first
            self.first = node
    # 队头移除元素
    def head_pop(self):
        if self.first is None:
            return None
        else:
            item = self.first
            self.first = self.first.next
            return item

    # 队尾添加元素
    def tail_push(self, item):
        node = Node(item)
        if self.first.item is None:
            self.first = node
            self.last = node
        else:
            self.last.next = node
            self.last = node

    # 从队尾移除元素
    def tail_pop(self):
        if self.last is None:
            return None
        else:
            item = self.last
            # 找到last的前一个节点
            cur = self.first
            pre = None
            while cur.next is not None:
                pre = cur
                cur = cur.next
            # 移除尾节点,重新给尾节点设置值
            pre.next = None
            self.last = pre
            return item


if __name__ == '__main__':
    deque = Deque()
    deque.head_push(1)
    deque.head_push(2)
    deque.head_push(3)
    deque.head_push(4)
    deque.head_push(5)
    deque.tail_pop()
    print(deque)

总结

以上就是自己通过实现数据结构学习Python的相关实现,由于是自己思考做的部分实现,并且测试用例并不完整,无法保证代码的完全正确性,如有错误欢迎指正讨论。

这其中的一些异常判断并不全面,运行这部分代码时建议通过debug的方式理解更好!