美文网首页
python进阶-08-数据结构

python进阶-08-数据结构

作者: 西海岸虎皮猫大人 | 来源:发表于2020-04-02 01:22 被阅读0次

    1 概念

    算法不关注处理何种数据,数据结构关注的是如何组织数据
    比如可以使用列表嵌套元组保存学生信息,也可使用列表嵌套字典,或者字典嵌套字典(学号作为key,其他作为value)
    如果使用列表保存,需要循环根据学号判断
    如果使用字典保存,可以直接根据学号的key获取

    2 顺序表

    顺序表,存储空间连续

    2.1 插入元素

    尾部插入,保序插入(当前位置到末尾所有元素后移),非保序插入(当前元素移至末尾+1)
    python中的list就是保序的线性表

    2.2 测试insert和append的执行效率

    timeit模块可以测试代码效率

    # coding=utf-8
    from timeit import Timer
    
    
    def append_test():
        li = []
        for i in range(10000):
            li.append(i)
    
    
    def insert_test():
        li = []
        for i in range(10000):
            li.insert(0,i)
    
    
    append_timer = Timer('append_test()', 'from __main__ import append_test')
    print('append插入执行时间', append_timer.timeit(1000))
    insert_timer = Timer('insert_test()', 'from __main__ import insert_test')
    print('insert插入执行时间', insert_timer.timeit(1000))
    

    测试结果

    append插入执行时间 1.1257968
    insert插入执行时间 41.978182499999996
    

    3 链表

    链表存储空间非连续,可以充分利用计算机空间
    每个节点保存下一元素的地址
    链表插入元素更加灵活

    3.1 单向链表
    # coding=utf-8
    
    
    # 节点类
    class Node(object):
        def __init__(self, elem):
            # elem指数据元素
            self.elem = elem
            # 指向下一个节点
            self.next = None
    
    
    # 单向链表类
    class SingleLinkList(object):
        def __init__(self, node=None):
            # 判断node是否为空
            if node != None:
                headNode = Node(node)
                self.__head = headNode
            else:
                self.__head = node
    
        # 头部添加元素
        def add(self, item):
            node = Node(item)
            node.next = self.__head
            self.__head = node
    
        # 尾部追加元素
        def append(self, item):
            node = Node(item)
            # 如果是空链表
            if self.is_empty():
                self.__head = node
            else:
                curNode = self.__head
                # 遍历得到最后节点
                while curNode.next != None:
                    curNode = curNode.next
                curNode.next = node
    
        # 指定位置添加元素
        def insert(self,pos,item):
            # 如果pos<0,默认插入头部
            if pos <= 0:
                self.add(item)
            # 如果pos值大于链表长度,默认插入尾部
            elif pos > self.length()-1:
                self.append(item)
            else:
                node = Node(item)
                count = 0
                preNode = self.__head
                while count<(pos-1):
                    count += 1
                    preNode = preNode.next
                # 修改指向
                node.next = preNode.next
                preNode.next = node
    
    
    
        # 删除元素
        def remove(self, item):
            preNode = None
            curNode = self.__head
            while curNode != None:
                if curNode.elem == item:
                    # 判断是否是头节点
                    if preNode == None:
                        # 删除头节点
                        self.__head = curNode.next
                    else:
                        # 删除
                        preNode.next = curNode.next
                    break
                else:
                    preNode = curNode
                    curNode = curNode.next
    
    
        # 查找节点是否存在
        def search(self, item):
            curNode = self.__head
            while curNode != None:
                if curNode.elem == item:
                    return True
                curNode = curNode.next
            return False
    
        # 判断链表是否为空
        def is_empty(self):
            # 判断head是否为None
            return self.__head == None
    
        # 计算链表长度
        def length(self):
            count = 0
            # 当前节点
            curNode = self.__head
            while curNode != None:
                count += 1
                # 当前节点指向下一节点
                curNode = curNode.next
            return count
    
        # 遍历
        def travel(self):
            curNode = self.__head
            print('遍历:', end='\t')
            while curNode != None:
                print(curNode.elem, end='\t')
                curNode = curNode.next
            print()
    
    # 测试
    if __name__ == '__main__':
        # 初始化一个元素值为20的单向链表
        singleLinkList = SingleLinkList(20)
        # 初始化一个空的的单向链表
        singleLinkList2 = SingleLinkList()
        print('判断链表是否为空:', singleLinkList.is_empty())
        print('链表长度:', singleLinkList.length())
        singleLinkList.travel()
        print('查找:', singleLinkList.search(20))
        singleLinkList.add(1)
        singleLinkList.add(2)
        singleLinkList.add(3)
        singleLinkList.travel()
        singleLinkList.append(4)
        singleLinkList.travel()
        singleLinkList2.append(4)
        singleLinkList2.travel()
        singleLinkList.insert(2, 100)
        singleLinkList.travel()
        singleLinkList.insert(-1, 200)
        singleLinkList.travel()
        singleLinkList.insert(100, 300)
        singleLinkList.travel()
        singleLinkList.remove(200)
        singleLinkList.travel()
        singleLinkList.remove(300)
        singleLinkList.travel()
    
    3.2 链表\顺序表对比

    存储空间,不连续\连续
    链表由于添加了指针域,空间开销比较大
    链表便于修改,顺序表便于查询

    3.3 双向链表

    每个节点存储前驱和后继节点
    双向链表初始化\查找\判断是否为空\计算长度\遍历方法与单向链表相同

    # coding=utf-8
    
    
    # 双向链表节点类
    class Node:
        def __init__(self,elem):
            self.elem = elem
            # 后继
            self.next = None
            # 前驱
            self.prev = None
    
    
    class DoubleLinkList:
        # 初始化方法
        def __init__(self, node=None):
            # 判断node是否为空
            if node != None:
                headNode = Node(node)
                self.__head = headNode
            else:
                self.__head = node
    
        # 头部添加元素
        def add(self, item):
            node = Node(item)
            # 判断是否为空链表
            if self.is_empty():
                self.__head = node
            else:
                node.next = self.__head
                self.__head.prev = node
                self.__head = node
    
        # 尾部追加元素
        def append(self, item):
            node = Node(item)
            # 如果是空链表
            if self.is_empty():
                self.__head = node
            else:
                curNode = self.__head
                # 遍历得到最后节点
                while curNode.next != None:
                    curNode = curNode.next
                node.prev = curNode
                curNode.next = node
    
        # 指定位置添加元素
        def insert(self,pos,item):
            # 如果pos<0,默认插入头部
            if pos <= 0:
                self.add(item)
            # 如果pos值大于链表长度,默认插入尾部
            elif pos > self.length()-1:
                self.append(item)
            else:
                node = Node(item)
                count = 0
                curNode = self.__head
                while count<(pos-1):
                    count += 1
                    curNode = curNode.next
                # node的前驱指向当前节点
                node.prev = curNode
                # node的后继指向当前节点的下一节点
                node.next = curNode.next
                # 当前节点下一节点的前驱指向node节点
                node.next.prev = node
                # 当前节点后继指向node节点
                curNode.next = node
    
    
    
        # 删除元素
        def remove(self, item):
            curNode = self.__head
            while curNode != None:
                if curNode.elem == item:
                    # 判断是否是头节点
                    if curNode == self.__head:
                        # 删除头节点
                        self.__head = curNode.next
                        # 判断当前节点是否只有一个节点
                        if curNode.next:
                            curNode.next.prev = None
                    else:
                        # 删除
                        curNode.prev.next = curNode.next
                        # 如果当前节点是最后节点,则下一节点没有前驱
                        if curNode.next:
                            curNode.next.prev = curNode.prev
                    break
                else:
                    curNode = curNode.next
    
    
        # 查找节点是否存在
        def search(self, item):
            curNode = self.__head
            while curNode != None:
                if curNode.elem == item:
                    return True
                curNode = curNode.next
            return False
    
        # 判断链表是否为空
        def is_empty(self):
            # 判断head是否为None
            return self.__head == None
    
        # 计算链表长度
        def length(self):
            count = 0
            # 当前节点
            curNode = self.__head
            while curNode != None:
                count += 1
                # 当前节点指向下一节点
                curNode = curNode.next
            return count
    
        # 遍历
        def travel(self):
            curNode = self.__head
            print('遍历:', end='\t')
            while curNode != None:
                print(curNode.elem, end='\t')
                curNode = curNode.next
            print()
    
    
    # 测试
    if __name__ == '__main__':
        doubleLinkList = DoubleLinkList()
        doubleLinkList.add(20)
        doubleLinkList.add(21)
        doubleLinkList.travel()
        doubleLinkList.append(22)
        doubleLinkList.travel()
        doubleLinkList.insert(1, 19)
        doubleLinkList.travel()
        doubleLinkList.remove(21)
        doubleLinkList.travel()
        doubleLinkList.remove(20)
        doubleLinkList.travel()
        doubleLinkList.remove(22)
        doubleLinkList.travel()
        print('链表长度:', doubleLinkList.length())
        print('查找元素:', doubleLinkList.search(19))
        print('查找元素:', doubleLinkList.search(20))
    

    4 栈

    栈由链表或顺序表实现
    栈只关心操作的实现->后进先出

    # coding=utf-8
    
    
    class Stack():
        def __init__(self):
            self.__list = []
    
        # 压栈
        def push(self, item):
            self.__list.append(item)
    
        # 弹出元素
        def pop(self):
            return self.__list.pop()
    
        # 返回栈顶元素
        def peek(self):
            return self.__list[len(self.__list)-1]
    
        # 判断栈是否为空
        def is_empty(self):
            return self.__list == []
    
        # 计算栈的大小
        def size(self):
            return len(self.__list)
    
    
    if __name__ == '__main__':
        stack = Stack()
        print('是否空栈:', stack.is_empty())
        # 压栈
        stack.push(1)
        stack.push(2)
        stack.push(3)
        print('栈长度:', stack.size())
        # 弹出
        print(stack.pop())
        print(stack.pop())
        print(stack.pop())
    

    5 队列

    先进先出

    # coding=utf-8
    
    
    class Queue:
        def __init__(self):
            self.__list = []
    
        # 进队
        def enqueue(self, item):
            # 进队频繁用append,出队频繁用insert
            self.__list.insert(0, item)
    
        # 出队
        def dequeue(self):
            return self.__list.pop()
    
        # 判断队列是否为空
        def is_empty(self):
            return self.__list == []
    
        # 计算队列大小
        def size(self):
            return len(self.__list)
    
    
    if __name__ == '__main__':
        queue = Queue()
        queue.enqueue(10)
        queue.enqueue(20)
        queue.enqueue(30)
        print(queue.is_empty())
        print(queue.size())
        print(queue.dequeue())
        print(queue.dequeue())
        print(queue.dequeue())
    

    6 树

    每个节点由0或多个子节点
    没有父节点的为根节点
    非根节点只有一个父节点
    每个字节点可以分为多个不相交的子树

    6.1 概念及应用场景

    节点的子节点的数目

    树的度

    最大节点的度

    有序树

    任意节点间有顺序关系

    二叉树

    每个节点最多有两个子树

    完全二叉树

    除最后一层外其他节点数目达到最大

    满二叉树

    最后一曾节点数达到最大

    平衡二叉树

    任意节点两颗子树高度差不大于1

    排序二叉树

    每个节点左侧小于该节点,右侧大于该节点

    应用场景:

    html\xml\mysql索引\路由协议\文件系统目录,以及一些AI算法如决策树

    6.2 二叉树

    第n层至多2^(n-1)个节点

    相关文章

      网友评论

          本文标题:python进阶-08-数据结构

          本文链接:https://www.haomeiwen.com/subject/bqctphtx.html