Python数据结构与算法 DAY 02 数据结构之链表&栈&队列

Python数据结构与算法 DAY 02 重点知识总结 链表的实现

一 单链表

单链表图例
在这里插入图片描述


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

class Method(object):
    # 创建初始值 将代表链首个节点的__head 定义并设置为None 即默认该链没有长度 也没有节点
    def __init__(self):
        self.__head = None

    # 判断 : 该链是否为空
    def is_empty(self):
        if self.__head == None:
            return True
        return False

    # 链的长度判断:
    #   这是其中一种判断方法 这种判断方法的优势在于 不会需要判断该链中是否有节点 因为如果本身是空链 是无法进入循环的 并且number的默认值为0
    def length(self):
        # 创建一个计数器 用于记录链的数量
        number = 0
        # 创建一个指针 首先指向链的第一个节点
        cur = self.__head
        # 创建一个循环 将这个循环从第一个节点进行到最后一个节点 (判断是否为最后一个节点的方法为判断 cur.next是否等于None)
        while cur != None:
            cur = cur.next
            number += 1
        return number

    # 增: 在链的最前端进行插入
    def insert_top(self,item):
        # 首先创造新的节点(使用Single类创建一个对象) 包含 item 和 next
        single = Single(item)
        # 将对象的next指向目前第一个节点 因为目前__head的已经指向了第一个节点 所以我们只需要和head指向的内容相同即可
        single.next = self.__head
        # 将head的指向转向新的节点
        self.__head = single

    # 增: 在链的末尾增加
    def insert_end(self,item):
        # 首先先创建一个新的节点(使用Single类创建一个对象) 包含item 和 next
        single = Single(item)
        # 由于是加在最后的 所以我们需要定义一个指针 并且让指针指向目前的最后一个
        cur = self.__head
        # 使用循环实现将指针指向最后目前最后一个节点
        while cur.next != None:
            # 将指针一次一次向后移动 移动到cur.next == None 为止
            cur = cur.next
        # 目前cur指针已经指向目前链的最后一个节点了 那么就将最后一个节点的next指向新创建的新节点即可(由于新节点的next默认为None 所以不需要重新设置)
        cur.next = single

    # 增: 输入插入的位置 在指定的位置插入新的节点 类似于列表内的insert的效果
    def insert_middle(self,indexs,item):
        '''
        :param indexs: 输入插入的索引 类型为整型int
        :param item: 插入的值 (用于创建新节点的对象)
        :return: None
        '''
        # 首先先创建一个新的节点
        single = Single(item)
        # 判断是否为空链
        if self.is_empty() == False:
            # 判断是否为输入的索引为开头
            if indexs<=0:
                self.insert_top(item)
            # 判断是否输入的索引为末尾
            elif indexs > (self.length()-1):
                self.insert_end(item)
            # 如果插入的位置是在中间
            else:
                # 创建一个指针 初始值为指向链的第一个节点
                cur = self.__head
                # 创建一个计数器 目的是判断指针是否移动到需要插入的位置的前一个节点
                count = 0
                # 写入循环 逻辑是只要计数器(反应的是当前指针指向的索引位置)
                while count < (indexs-1):
                    cur = cur.next
                    count += 1
                # 将新的节点指向目前当前位置之后的节点
                single.next = cur.next
                # 将目前的节点的next指向新创建的节点
                cur.next = single
        else:
            print('本链为空 默认插入的索引为0')
            self.insert_top(item)

    # 删除 : 删除其中一个元素
    def _delete(self,indexs):
        '''
        :param indexs: 需要删除的元素的索引
        :return:
        '''
        # 判断该链是否为空链
        if self.is_empty() == False:
            # 创建游标cur
            cur = self.__head
            # 创建新游标 precur 这个游标的进度会比cur慢一个单位 也就是指向的是cur上一个节点
            precur = None
            # 判断输入的indexs是否为链的首个
            if indexs <= 0:
                self.__head = cur.next
                cur.next = None
            # 判断输入的indexs是否为链的末尾
            elif indexs >= (self.length() - 1):
                # 这里写判断条件 目的是 经过循环之后 输出的cur指向的是最后一个节点 而pre指向的是倒数第二个节点
                while cur.next != None:
                    precur = cur
                    cur = cur.next
                # 变换指向 将需要删除目标的上一个节点的next 指向 None
                precur.next = None
            # 若输入的indexs是否为链的中间
            else:
                # 设置计数器 计数器反应的部分即为cur的索引
                count = 0
                # 设置循环 设置判断条件 让循环结束后 cur指向需要删除的目标索引节点 precur指向删除目标节点上一个节点
                while count < indexs:
                    precur = cur
                    cur = cur.next
                    count += 1
                # 变换指向 将需要删除目标的上一个节点的next 指向 需要删除目标后面的节点
                precur.next = cur.next
                # 将需要删除目标的next设置为None
                cur.next = None
        else:
            print('error,该链为空')

    # 查找该节点是否存在
    def seaching(self,item):
        # 设置指针 并默认指向head
        cur = self.__head
        # 设置循环 循环判断指向的节点的item值和输入的item值是否相同 相同则输出True 并且停止循环
        while cur != None:
            if cur.item == item:
                return True
            else:
                cur = cur.next
        # 如果遍历结束没有找到 则返回False
        else:
            return False

    # 遍历链
    def travel(self):
        # 创建指针
        cur = self.__head
        while cur != None:
            print(cur.item,end='  ')
            cur = cur.next
        else:
            print()


if __name__ == "__main__":
    ll = Method()
    ll.insert_top(1)
    ll.insert_top(2)
    ll.insert_end(3)
    ll.insert_middle(2, 4)
    print ("length:",ll.length())
    ll.travel()
    print( ll.seaching(3))
    print (ll.seaching(5))
    ll._delete(1)
    print ("length:",ll.length())
    ll.travel()

二 单向循环链表

单向循环链表图例
在这里插入图片描述
代码实现:

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

class Method(object):
    def __init__(self):
        self.__head = None

    def is_empty(self):
        if self.__head == None:
            return True
        else:
            return False

    def length(self):
        if self.is_empty() == True:
            return 0
        else:
            count = 1
            cur = self.__head
            while cur.next != self.__head:
                cur = cur.next
                count += 1
            return count

    def traval(self):
        if self.is_empty():
            return 'empty'
        else:
            cur = self.__head
            while cur.next != self.__head:
                print(cur.item,end = ',')
                cur = cur.next
            print(cur.item)

    def insert_top(self,item):
        cur = self.__head
        single = Single(item)
        if self.is_empty() == True:
            self.__head = single
            single.next = single
        else:
            single.next = cur
            while cur.next != self.__head:
                cur = cur.next
            cur.next = single
            self.__head = single

    def insert_end(self,item):
        if self.is_empty():
            self.insert_top()
        else:
            cur = self.__head
            single = Single(item)
            single.next = self.__head
            while cur.next != self.__head:
                cur = cur.next
            cur.next = single

    def insert_middle(self,indexs,item):
        if indexs<=0:
            self.insert_top(item)
        elif indexs>(self.length() - 1):
            self.insert_end(item)
        else:
            cur = self.__head
            single = Single(item)
            count = 0
            while count < (indexs -1):
                cur = cur.next
                count += 1
            single.next = cur.next
            cur.next = single

    def is_exist(self,item):
        if self.is_empty():
            return 'error,empty'
        else:
            cur = self.__head
            while cur.next != self.__head:
                if item == cur.item:
                    return True
                else:
                    cur = cur.next
            else:
                if item == cur.item:
                    return True
                else:return False

    def delete_(self,item):
        if not self.is_exist(item):
            print(f'"{item}" is not in this chain')
            return
        # 判断该节点是否为空节点
        elif self.is_empty():
            print('there are nothing in this chain')
            return

        # 设置开头cur : head_cur
        head_cur = self.__head
        # 设置末尾cur : end_cur
        cur = self.__head
        while cur.next != self.__head:
            cur = cur.next
        end_cur = cur
        # 重新设置移动cur
        cur = self.__head

        # 判断该链中是否只有一个节点
        if self.length() == 1:
            if item == cur.item:
                self.__head = None
                return
            else:
                print(f'"{item}" is not in this chain')
                return

        else: # elif self.length() > 1:
            # 删除首个
            if item == head_cur.item:
                while cur.next != self.__head:
                    cur = cur.next
                cur.next = head_cur.next
                self.__head = head_cur.next
                return
            # 删除末尾
            elif item == end_cur.item:
                pre = self.__head
                while pre.next != end_cur:
                    pre = pre.next
                pre.next = head_cur
                return
            # 删除中间
            else:
                pre = None
                while cur.item != item:
                    pre = cur
                    cur = cur.next
                pre.next = cur.next
                return


# 测试
if __name__ == '__main__':
    t1 = Method()
    # print(t1.is_empty()) # True
    # print(t1.length()) # 0
    t1.insert_top(1)
    t1.insert_top(5)
    t1.insert_end(10)
    t1.insert_top(6)
    # t1.traval() # 6,5,1,10
    t1.insert_middle(2,4)
    # t1.traval() # 6,5,4,1,10
    # print(t1.is_exist(11))

    t1.delete_(6)
    t1.traval() # 5,4,1,10
    t1.delete_(10)
    t1.traval() # 5,4,1
    t1.delete_(5)
    t1.delete_(4)
    t1.traval() # 1
    t1.delete_(10) # "10" is not in this chain
    t1.delete_(1)
    t1.traval()
    t1.delete_(10)

三 双向链表

双向链表图例
在这里插入图片描述
双向链表的代码实现:

class Node:
    def __init__(self, elem):
        self.elem = elem
        self.next = None
        self.pre = None


class DoubleLink():

    def __init__(self):
        self.__head = None

    def is_empty(self):
        if self.__head is None:
            return True
        else:
            return False

    def length(self):
        cur = self.__head
        count = 0
        while cur != None:
            cur = cur.next
            count += 1
        return count

    # 循环打印链表的值
    def travel(self):
        if self.is_empty():
            return

        cur = self.__head
        while cur != None:
            print(cur.elem, end=',')
            cur = cur.next
        print()


    # 在头部添加数据
    def add(self, item):

        node = Node(item)

        if not self.is_empty():
            node.next = self.__head

            self.__head.pre = node

        self.__head = node


    # 在尾部添加
    def append(self, item):
        if self.is_empty():
            self.add(item)
        else:
            node = Node(item)

            cur = self.__head

            while cur.next != None:
                cur = cur.next

            cur.next = node
            node.pre = cur


    def insert(self, pos, item):
        if pos <= 0:
            self.add(item)
        elif pos > self.length() - 1:
            self.append(item)
        else:
            node = Node(item)

            cur = self.__head

            count = 0

            while count < pos:
                count += 1
                cur = cur.next

            node.next = cur
            node.pre = cur.pre
            cur.pre.next = node
            cur.pre = node

    def remove(self, item):

        if self.is_empty():
            return None

        cur = self.__head

        while cur.next != None:

            # 找到节点
            if cur.elem == item:
                # 如果在第一个位置就找到节点
                if cur == self.__head:
                    self.__head = cur.next
                    cur.next.pre = None
                else:
                    cur.pre.next = cur.next
                    cur.next.pre = cur.pre
                return
            else:
                cur = cur.next

        if cur.elem == item:
            # 只有一个节点
            if cur.pre == None:
                self.__head = None
            else:
                # 最后一个节点
                cur.pre.next = None



    def search(self, item):

        cur = self.__head

        while cur != None:

            if cur.elem == item:
                return True

            cur = cur.next

        return False


if __name__ == '__main__':

    s = DoubleLink()
    print(s.is_empty())
    s.add(100)
    s.add(10)
    s.add(20)
    print(s.is_empty())
    print(s.length())
    s.travel()
    s.append(300)
    s.travel()
    # 20 10 100 300
    s.insert(2, 40)
    s.travel()
    s.insert(0, 110)
    s.travel()
    s.insert(100,330)
    s.travel()
    # 110, 20, 10, 40, 100, 300, 330
    s.remove(40)
    s.travel()
    s.remove(110)
    s.travel()
    s.remove(330)
    # 20,10,40,300
    s.travel()
    print(s.search(10))
    print(s.search(120))

四 栈

栈可以使用顺序表实现 也可以使用链表实现 我们这里封装的是使用顺序表来实现

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

class Stack():

    def __init__(self):
        self.item = []

    def push(self, item):
        # 添加一个新的元素item到栈顶
        self.item.insert(0, item)

    def pop(self):
        # 弹出栈顶元素
        self.item.pop(0)

    def peek(self):
        # 返回栈顶元素
        return self.item[0]

    def is_empty(self):
        # 判断栈是否为空
        if not self.item:
            return True
        else:
            return False

    def size(self):
        # 返回栈的元素个数
        return len(self.item)

五 队列

同栈一样,队列也可以用顺序表或者链表实现。

Queue() 创建一个空的队列
enqueue(item) 往队列中添加一个item元素
dequeue() 从队列头部删除一个元素
is_empty() 判断一个队列是否为空
size() 返回队列的大小

class Queue(object):
    """队列"""
    def __init__(self):
        self.items = []

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

    def enqueue(self, item):
        """进队列"""
        self.items.insert(0,item)

    def dequeue(self):
        """出队列"""
        return self.items.pop()

    def size(self):
        """返回大小"""
        return len(self.items)

if __name__ == "__main__":
    q = Queue()
    q.enqueue("hello")
    q.enqueue("world")
    q.enqueue("haha")
    print q.size()
    print q.dequeue()
    print q.dequeue()
    print q.dequeue()

六 双端队列

双端队列(deque,全名double-ended queue),是一种具有队列和栈的性质的数据结构。

双端队列中的元素可以从两端弹出,其限定插入和删除操作在表的两端进行。双端队列可以在队列任意一端入队和出队。

Deque() 创建一个空的双端队列
add_front(item) 从队头加入一个item元素
add_rear(item) 从队尾加入一个item元素
remove_front() 从队头删除一个item元素
remove_rear() 从队尾删除一个item元素
is_empty() 判断双端队列是否为空
size() 返回队列的大小

class Deque(object):
    """双端队列"""
    def __init__(self):
        self.items = []

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

    def add_front(self, item):
        """在队头添加元素"""
        self.items.insert(0,item)

    def add_rear(self, item):
        """在队尾添加元素"""
        self.items.append(item)

    def remove_front(self):
        """从队头删除元素"""
        return self.items.pop(0)

    def remove_rear(self):
        """从队尾删除元素"""
        return self.items.pop()

    def size(self):
        """返回队列大小"""
        return len(self.items)


if __name__ == "__main__":
    deque = Deque()
    deque.add_front(1)
    deque.add_front(2)
    deque.add_rear(3)
    deque.add_rear(4)
    print deque.size()
    print deque.remove_front()
    print deque.remove_front()
    print deque.remove_rear()
    print deque.remove_rear()
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值