zoukankan      html  css  js  c++  java
  • 数据结构-python

    1 概念

    1.1 时间复杂度

    假设存在函数g,使得算法A处理规模为n的问题示例所用时间为T(n)=O(g(n))则称T(n)为算法A的渐近时间复杂度,简称时间复杂度。

    g(n)则称为一个时间复杂度的大O表示法。

    渐近函数定义:考虑一个函数  ,我们需要了解当  变得非常大的时候  的性质。令  ,在 特别大的时候,第二项 

                               

    比起第一项  要小很多。于是对于这个函数,有如下断言:    的情况下与  渐近等价”,记作  

    最坏时间复杂度:算法完成工作最多需要多少基本操作。

    时间复杂度的基本计算规则:

    1. 基本操作,即只有常数项,认为其时间复杂度为O(1)
    2. 顺序结构,时间复杂度按加法进行计算
    3. 循环结构,时间复杂度按乘法进行计算
    4. 分支结构,时间复杂度取最大值
    5. 判断一个算法的效率时,往往只需要关注操作数量的最高次项,其它次要项和常数项可以忽略

    常见时间复杂度:

    执行次数函数举例非正式术语
    12 O(1) 常数阶
    2n+3 O(n) 线性阶
    3n^2+2n+1 O(n^2) 平方阶
    5log2n+20 O(logn) 对数阶
    2n+3nlog2n+19 O(nlogn) nlogn阶
    6n^3+2n^2+3n+4 O(n^3) 立方阶
    2^n O(2^n) 指数阶

    常见时间复杂度之间的关系:

    所消耗的时间从小到大:O(1) < O(logn) < O(n) < O(nlogn) < O(n^2) < O(n^3) < O(2^n) < O(n!) < O(n^n)

    1.2 timeit模块(python内置模块分析性能)

    class timeit.Timer(stmt='代码', setup='运行代码的设置', timer=<定时器函数>)

    timeit.Timer.timeit(number=1000000):Timer类中测试语句执行速度的对象方法。number参数是测试代码时的测试次数。

    def cal():
        for a in range(1001):
            for b in range(1001-a):
                c = 1000-a-b
                if  a**2 + b**2 == c**2 :
                    return a,b,c
    
    t = timeit.Timer('cal()','from __main__ import cal')
    print(t.timeit(number=1000))

    1.3 数据结构

    数据结构只是静态的描述了数据元素之间的关系。Python的内置数据结构:列表、元组、字典。

    程序 = 数据结构 + 算法 

    抽象数据类型(ADT):一个数学模型以及定义在此数学模型上的一组操作。

    常用数据运算:插入、删除、修改、查找、排序。

    2 线性表

    • 顺序表,将元素顺序地存放在一块连续的存储区里,元素间的顺序关系由它们的存储顺序自然表示。
    • 链表,将元素存放在通过链接构造起来的一系列存储块中。

    2.1 顺序表

    eg.python中list为线性表。

    eg.int类型在32位计算机中,存储空间为4个字节(8位),在内存中按照连续存储单元(1个字节)进行存储。

         1、连续存储元素信息   2、连续存储地址信息

    2.1.1 线性表结构

    线性表的空间是固定的,若要进行扩充:1、增加固定数目  2、每次扩充容量加倍

    头部插入数据时间复杂度为O(1),中间插入和尾部插入时间复杂度为O(n)。

    list内置操作的时间复杂度:

    dict内置操作的时间复杂度:

    2.2 链表

    在每一个节点(数据存储单元)里存放下一个节点的位置信息(即地址)。链表需要额外开销存储位置信息,但是在内存中是分散存储的,所以可以充分离散的内存空间。

    2.2.1 单向链表

    class SingleNode(object):
        '''节点'''
        def __init__(self,item):
            self.elem = item
            self.next = None
    
    class SingleLink(object):
        def __init__(self):
            self.__head =None
    
        def is_empty(self):
            '''链表是否为空'''
            return self.__head ==None
    
        def length(self):
            '''链表长度'''
            #cur游标,用来移动遍历节点
            cur = self.__head
            count = 0
            while cur != None:
                count +=1
                cur = cur.next
            return count
    
        def travel(self):
            '''遍历整个链表'''
            cur = self.__head
            while cur != None:
                print(cur.elem,end= '')
                cur = cur.next
    
        def add(self,item):
            '''链表头部添加元素'''
            # 先创建一个保存item值的节点
            node = SingleNode(item)
            node.next = self.__head
            self.__head = node
    
        def append(self,item):
            '''链表尾部添加元素'''
            node = SingleNode(item)
            if self.__head == None:
                self.__head = node
            else:
                cur = self.__head
                while cur.next != None:
                    cur = cur.next
                cur.next = node
    
        def insert(self,pos,item):
            '''指定位置添加元素'''
            node = SingleNode(item)
            cur = self.__head
            if pos ==0:
                node.next = cur
                self.__head = node
            elif self.length()-1< pos:
                while cur != None:
                    cur = cur.next
                cur.next =item
            else:
                count = 0
                while count != pos-1:
                    count +=1
                    cur = cur.next
                node.next = cur.next
                cur.next = node
    
        def remove(self,item):
            '''指定元素删除节点'''
            node = SingleNode(item)
            cur = self.__head
            pre = None
            while cur!= None:
                if cur.elem == node.elem:
                    # 如果第一个就是删除的节点
                    if not pre:
                        self.__head = cur.next
                    else:
                        pre.next = cur.next
                    break
                else:
                    pre = cur
                    cur = cur.next
    
        def search(self,item):
            '''查找节点是否存在'''
            cur = self.__head
            node = SingleNode(item)
            while cur !=None:
                if cur.elem == node.elem:
                    return True
                else:
                    cur = cur.next
            return False
    
    if __name__ == '__main__':
        l = SingleLink()
        print(l.is_empty())
        l.add(1)
        l.add(2)
        l.append(0)
        l.insert(0,3)
        l.insert(2, 0)
        l.remove(0)
        l.remove(4)
        print(l.is_empty())
        print(l.search(4))
        print(l.search(0))
        print(l.length())
        l.travel()

    2.2.2 双向链表

    class DoubleNode(object):
        def __init__(self,item):
            self.elem = item
            self.pre = None
            self.next = None
    
    class DoubleLink(object):
        def __init__(self):
            self.__head = None
    
        def is_empty(self):
            return  self.__head == None
    
        def length(self):
            cur = self.__head
            count = 0
            while cur!=None:
                count +=1
                cur= cur.next
            return count
    
        def travel(self):
            cur = self.__head
            if self.__head ==None:
                return
            else:
                while cur!=None:
                    print(cur.elem,end="")
                    cur = cur.next
                print("")
    
        def add(self,item):
            node = DoubleNode(item)
            if self.__head ==None:
                self.__head = node
            else:
                node.next =self.__head
                self.__head.pre = node
                self.__head = node
    
        def append(self,item):
            node =DoubleNode(item)
            if self.__head ==None:
                self.__head = node
            else:
                cur = self.__head
                while cur.next!=None:
                    cur = cur.next
                node.pre = cur
                cur.next = node
    
        def insert(self,pos,item):
            node = DoubleNode(item)
            if pos <=0:
                self.add(item)
            elif pos >= self.length():
                self.append(item)
            else:
                count = 0
                cur = self.__head
                if 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):
            node = DoubleNode(item)
            if self.__head ==None:
                return
            else:
                cur = self.__head
                if cur.elem == item:
                    # 如果首节点的元素即是要删除的元素
                    if cur.next == None:
                        # 如果链表只有这一个节点
                        self.__head = None
                    else:
                        # 将第二个节点的prev设置为None
                        cur.next.pre = None
                        # 将_head指向第二个节点
                        self.__head = cur.next
                    return
                while cur.next!= None:
                    if cur.elem == item:
                        # 将cur的前一个节点的next指向cur的后一个节点
                        cur.pre.next = cur.next
                        # 将cur的后一个节点的prev指向cur的前一个节点
                        cur.next.pre = cur.pre
                        break
                    cur = cur.next
                #删除的是最后一个
                if cur.elem ==item:
                    cur.pre.next = None
                else:
                    return
    
        def search(self,item):
            node = DoubleNode(item)
            cur = self.__head
            while cur !=None:
                if cur.elem != node.elem:
                    cur =cur.next
                else:
                    return True
            return False

    2.2.3 单向循环列表

    class SingleCircleNode(object):
        def __init__(self,item):
            self.elem = item
            self.node =None
    
    class SingleCircleLink(object):
        def __init__(self):
            self.__head = None
    
        def is_empty(self):
            return  self.__head == None
    
        def length(self):
            if self.__head == None:
                return 0
            else:
                count = 1
                cur = self.__head
                while cur.next != self.__head:
                    count +=1
                    cur = cur.next
                return count
    
        def travel(self):
            if self.__head == None:
                return
            else:
                cur = self.__head
                while cur.next !=self.__head:
                    print(cur.elem,end="")
                    cur = cur.next
                print(cur.elem)
    
        def add(self,item):
            node = SingleCircleNode(item)
            if self.__head == None:
                self.__head = node
                node.next = self.__head
            else:
                cur = self.__head
                while cur.next !=self.__head:
                    cur = cur.next
                node.next = self.__head
                self.__head = node
                cur.next = self.__head
    
        def append(self,item):
            node = SingleCircleNode(item)
            if self.__head ==None:
                self.__head = node
                node.next = self.__head
            else:
                cur = self.__head
                while cur.next !=self.__head:
                    cur =cur.next
                node.next = self.__head
                cur.next = node
    
    
        def insert(self,pos,item):
            node = SingleCircleNode(item)
            if pos <=0:
                self.add(item)
            elif pos >= self.length():
                self.append(item)
            else:
                count =1
                cur = self.__head
                while pos !=count:
                    count +=1
                    cur = cur.next
                node.next = cur.next
                cur.next = node
    
        def remove(self,item):
            """删除一个节点"""
            # 若链表为空,则直接返回
            if self.is_empty():
                return
            # 将cur指向头节点
            cur = self.__head
            pre = None
            # 若头节点的元素就是要查找的元素item
            if cur.elem == item:
                # 如果链表不止一个节点
                if cur.next != self.__head:
                    # 先找到尾节点,将尾节点的next指向第二个节点
                    while cur.next != self.__head:
                        cur = cur.next
                    # cur指向了尾节点
                    cur.next = self.__head.next
                    self.__head = self.__head.next
                else:
                    # 链表只有一个节点
                    self.__head = None
            else:
                pre = self.__head
                # 第一个节点不是要删除的
                while cur.next != self.__head:
                    # 找到了要删除的元素
                    if cur.elem == item:
                        # 删除
                        pre.next = cur.next
                        return
                    else:
                        pre = cur
                        cur = cur.next
                # cur 指向尾节点
                if cur.elem == item:
                    # 尾部删除
                    pre.next = cur.next
    
            # node = SingleCircleNode(item)
            # if self.__head == None:
            #     return
            # cur = self.__head
            # pre = None
            # while cur.next != self.__head:
            #     if cur.elem == node.elem:
            #         if pre is None:
            #             rear = self.__head
            #             while rear.next != self.__head:
            #                 rear = rear.next
            #             self.__head = cur.next
            #             rear.next = self.__head
            #         else:
            #             pre.next = cur.next
            #         break
            #     else:
            #         pre = cur
            #         cur = cur.next
            # if cur.elem == node.elem:
            #     #匹配只有一个元素且是第一个元素
            #     if pre is None:
            #         self.__head ==None
            #     #匹配最后一个元素
            #     else:
            #         pre.next = self.__head
            # else:
            #     return
    
            # else:
            #     cur = self.__head
            #     pre = None
            #     if cur.elem == node.elem:
            #         if cur.next == None:
            #             self.__head = None
            #         else:
            #             node.next = cur.next
            #             self.__head = node
            #     while cur.next != self.__head:
            #         if cur.elem == node.elem:
            #             pre.next = cur.next
            #         else:
            #             pre = cur
            #             cur = cur.next
            #         break
            #     if cur.elem == node.elem:
            #         pre.next = self.__head
            #     else:
            #         return
    
        def search(self,item):
            if self.__head ==None:
                return False
            else:
                cur = self.__head
                while cur.next != self.__head:
                    if cur.elem == item:
                        return True
                    else:
                        cur =cur.next
                if cur.next == item:
                    return True
                else:
                    return False

    3 栈(stack)

    也称堆栈,是一种容器,可存入数据元素、访问元素、删除元素。由于栈数据结构只允许在一端进行操作,因而按照后进先出(LIFO, Last In First Out)的原理运作。

    class Stack(object):
        def __init__(self):
            self.items = []
    
        def is_empty(self):
            '''判断栈是否为空'''
            return self.items ==[]
    
        def size(self):
            '''返回栈的元素个数'''
            return len(self.items)
    
        def push(self,item):
            '''添加一个新的元素item到栈顶'''
            self.items.append(item)
    
        def pop(self):
            '''弹出栈顶元素'''
            return self.items.pop()
    
        def peek(self):
            '''返回栈顶元素'''
            return self.items[len(self.items)-1]
    
    if __name__ == '__main__':
        s = Stack()
        s.push(1)
        s.push(2)
        print(s.pop())
        print(s.peek())

    4 队列(queue)

    class Queue(object):
        def __init__(self):
            self.items = []
    
        def is_empty(self):
            '''判断一个队列是否为空'''
            return self.items == []
    
        def size(self):
            '''返回队列的大小'''
            return len(self.items)
    
        def enqueue(self,item):
            '''往队列中添加一个item元素'''
            self.items.append(item)
    
        def dequeue(self):
            '''从队列头部删除一个元素'''
            return self.items.pop(0)

    4.1 双端队列

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

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

    class Deque(object):
        '''创建一个空的双端队列'''
        def __init__(self):
            self.items = []
    
        def is_empty(self):
            '''判断双端队列是否为空'''
            return self.items == []
    
        def size(self):
            '''返回队列的大小'''
            return len(self.items)
    
        def add_front(self,item):
            '''从队头加入一个item元素'''
            self.items.insert(0,item)
    
        def add_rear(self,item):
            '''从队尾加入一个item元素'''
            self.items.append(item)
    
        def remove_front(self):
            '''从队头删除一个item元素'''
            return self.items.pop(0)
    
        def remove_rear(self):
            '''从队尾删除一个item元素'''
            return self.items.pop()

    5 排序与算法

    算法的稳定性:稳定性:稳定排序算法会让原本有相等键值的纪录维持相对次序。

    5.1 冒泡排序(Bubble Sort)

    冒泡排序算法如下:

    • 比较相邻的元素。如果第一个比第二个大(升序),就交换他们两个。
    • 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
    • 针对所有的元素重复以上的步骤,除了最后一个。
    • 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

     时间复杂度:

    • 最优时间复杂度:O(n) (表示遍历一次发现没有任何可以交换的元素,排序结束。)
    • 最坏时间复杂度:O(n2)
    • 稳定性:稳定
    def BubbleSort(alist):
    
        n = len(alist)
    count =0
    for j in range(n-1): for i in range(n-1-j): if alist[i] > alist[i+1]: alist[i],alist[i+1] = alist[i+1],alist[i]
    count +=1
    if count ==0
    return
    if __name__ == '__main__': alist = [7,2,5,7,1,9,0,3,4] BubbleSort(alist) print(alist)

    5.2 选择排序(Selection sort)

    • 在未排序序列中找到最小(大)元素,存放到排序序列的起始位置
    • 再从剩余未排序元素中继续寻找最小(大)元素,放到已排序序列的末尾
    • 以此类推,直到所有元素均排序完毕

    时间复杂度:

    • 最优时间复杂度:O(n2)
    • 最坏时间复杂度:O(n2)
    • 稳定性:不稳定(考虑升序每次选择最大的情况)
    def SelectionSort(alist):
    
        n = len(alist)
        for j in range(n-1):
            min_index = j
            for i in range(j+1,n):
                if alist[min_index] > alist[i]:
                    min_index=i
            alist[min_index],alist[j] = alist[j],alist[min_index]
    
    if __name__ == '__main__':
        alist = [7,2,5,7,1,9,0,3,4]
        SelectionSort(alist)
        print(alist)

    5.3 插入排序(Insertion Sort)

    通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。 

    时间复杂度:

    • 最优时间复杂度:O(n) (升序排列,序列已经处于升序状态)
    • 最坏时间复杂度:O(n2)
    • 稳定性:稳定
    def InsertionSort(alist):
        n = len(alist)
        for i in range(n):
            while i>0:
                if alist[i] < alist[i-1]:
                    alist[i],alist[i-1]=alist[i-1],alist[i]
                i -=1
    
    if __name__ == '__main__':
        alist = [7,2,5,7,1,9,0,3,4]
        InsertionSort(alist)
        print(alist)

    5.4 希尔排序(Shell Sort)

    也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。

    时间复杂度:

    • 最优时间复杂度:根据步长序列的不同而不同
    • 最坏时间复杂度:O(n2)
    • 稳定想:不稳定
    def ShellSort(alist):
    
        n = len(alist)
        gap = n//2
        while gap >0:
            for i in range(gap,n):
                while i>0:
                    if alist[i] < alist[i-gap]:
                        alist[i],alist[i-gap]= alist[i-gap],alist[i]
                    i -=gap
            gap = gap//2
    
    if __name__ == '__main__':
        alist = [7,2,5,7,1,9,0,3,4]
        ShellSort(alist)
        print(alist)

    5.5 快速排序(Quick Sort)

    也称划分交换排序(partition-exchange sort)

    快速排序步骤为:

    1. 从数列中挑出一个元素,称为"基准"(pivot);
    2. 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
    3. 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序,递归的最底部情形,是数列的大小是零或一。

    时间复杂度:

    • 最优时间复杂度:O(nlogn)
    • 最坏时间复杂度:O(n2)
    • 稳定性:不稳定
    def QuickSort(alist,first,last):
    
        if first >= last:
            return
        mid = alist[first]
        low = first
        high = last
        while low<high:
            while low<high and alist[high]>=mid:
                high -=1
            alist[high],alist[low]=alist[low],alist[high]
            while low <high and alist[low]<mid:
                low +=1
            alist[low],alist[high]=alist[high],alist[low]
        alist[low]=mid
        QuickSort(alist,first,low-1)
        QuickSort(alist,low+1,last)
    
    if __name__ == '__main__':
        alist = [7,2,5,7,1,9,0,3,4]
        QuickSort(alist,0,len(alist)-1)
        print(alist)

    5.6 归并排序

    归并排序的思想就是先递归分解数组,再合并数组。

    将数组分解最小之后,比较两个数组的最前面的数,谁小就先取谁,取了后相应的指针就往后移一位。然后再比较,直至一个数组为空,最后把另一个数组的剩余部分复制过来即可。

    时间复杂度:

    • 最优时间复杂度:O(nlogn)
    • 最坏时间复杂度:O(nlogn)
    • 稳定性:稳定
    def MergeSort(alist):
    
        n = len(alist)
        if n <=1:
            return alist
        mid = n//2
        left_list = MergeSort(alist[:mid])
        right_list = MergeSort(alist[mid:])
        left_point,right_point = 0,0
        result = []
        while left_point<len(left_list) and right_point<len(right_list):
            if left_list[left_point] <= right_list[right_point]:
                result.append(left_list[left_point])
                left_point +=1
            else:
                result.append(right_list[right_point])
                right_point+=1
        #将循环剩下的的元素添加到列表的最后
        result += left_list[left_point:]
        result += right_list[right_point:]
        return result
    
    if __name__ == '__main__':
        alist = [7,2,5,7,1,9,0,3,4]
        l = MergeSort(alist)
        print(l)

    5.7 算法效率比较

    5.8 搜索

    搜索的几种常见方法:顺序查找、二分法查找、二叉树查找、哈希查找

    二分查找:作用于有序的线性表。

    时间复杂度:

    • 最优时间复杂度:O(1)
    • 最坏时间复杂度:O(logn)
    def BinarySearch(alist,item):
    
        if len(alist) == 0:
            return False
        else:
            mid = len(alist)//2
            if alist[mid] == item:
                return True
            elif alist[mid] > item:
                return  BinarySearch(alist[:mid-1],item)
            else:
                return  BinarySearch(alist[mid+1:],item)
    
    if __name__ =='__main__':
    
        print(BinarySearch([4,6,7,8],4))

    6 树与树的算法

    树的概念:树(tree)是一种抽象数据类型(ADT)或是实作这种抽象数据类型的数据结构。

    特点:

    • 每个节点有零个或多个子节点;
    • 没有父节点的节点称为根节点;
    • 每一个非根节点有且只有一个父节点;
    • 除了根节点外,每个子节点可以分为多个不相交的子树。

    术语:

    • 节点的度:一个节点含有的子树的个数称为该节点的度;
    • 树的度:一棵树中,最大的节点的度称为树的度;
    • 叶节点或终端节点:度为零的节点;
    • 父亲节点或父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点;
    • 孩子节点或子节点:一个节点含有的子树的根节点称为该节点的子节点;
    • 兄弟节点:具有相同父节点的节点互称为兄弟节点;
    • 节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推;
    • 树的高度或深度:树中节点的最大层次;
    • 堂兄弟节点:父节点在同一层的节点互为堂兄弟;
    • 节点的祖先:从根到该节点所经分支上的所有节点;
    • 子孙:以某节点为根的子树中任一节点都称为该节点的子孙。
    • 森林:由m(m>=0)棵互不相交的树的集合称为森林。

    种类:

    • 无序树:树中任意节点的子节点之间没有顺序关系,这种树称为无序树,也称为自由树;
    • 有序树:树中任意节点的子节点之间有顺序关系,这种树称为有序树;
      • 二叉树:每个节点最多含有两个子树的树称为二叉树;
        • 完全二叉树:对于一颗二叉树,假设其深度为d(d>1)。除了第d层外,其它各层的节点数目均已达最大值,且第d层所有节点从左向右连续地紧密排列,这样的二叉树被称为完全二叉树,其中满二叉树的定义是所有叶节点都在最底层的完全二叉树;
        • 平衡二叉树(AVL树):当且仅当任何节点的两棵子树的高度差不大于1的二叉树;
        • 排序二叉树(二叉查找树(英语:Binary Search Tree),也称二叉搜索树、有序二叉树);
      • 霍夫曼树(用于信息编码):带权路径最短的二叉树称为哈夫曼树或最优二叉树;
      • B树:一种对读写操作进行优化的自平衡的二叉查找树,能够保持数据有序,拥有多余两个子树。

    存储:顺序存储和链式存储(通过lchild和rchild指针)。

    class Node(object):
    
        def __init__(self,item,lchild=None,rchild=None):
            self.root = item
            self.lchild = lchild
            self.rchild = rchild
    
    class Tree(object):
    
        def __init__(self,root=None):
            self.root = root
    
        def add(self,elem):
            node = Node(elem)
            if self.root ==Node:
                self.root = node
            #如果根节点不为空
            else:
                queue = []
                queue.append(self.root)
                while queue:
                    cur = queue.pop(0)
                    if cur.lchild == Node:
                        cur.lchild ==node
                        return 
                    elif cur.rchild ==None:
                        cur.rchild ==node
                        return 
                    else:
                        queue.append(cur.lchild)
                        queue.append(cur.rchild)

    6.1 二叉树

    二叉树是每个节点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。

    性质:

    • 在二叉树的第i层上至多有2^(i-1)个结点(i>0)
    • 深度为k的二叉树至多有2^k - 1个结点(k>0)
    • 对于任意一棵二叉树,如果其叶结点数为N0,而度数为2的结点总数为N2,则N0=N2+1;
    • 具有n个结点的完全二叉树的深度必为 log2(n+1)
    • 对完全二叉树,若从上至下、从左至右编号,则编号为i 的结点,其左孩子编号必为2i,其右孩子编号必为2i+1;其双亲的编号必为i/2(i=1 时为根除外)

    6.2 二叉树的遍历

    深度优先遍历和广度优先遍历,深度优先一般用递归,广度优先一般用队列。

    6.2.1 广度遍历(层次遍历)

    def breadth_travel(self, root):
            """利用队列实现树的层次遍历"""
            if root == None:
                return
            queue = []
            queue.append(root)
            while queue:
                node = queue.pop(0)
                print (node.elem)
                if node.lchild != None:
                    queue.append(node.lchild)
                if node.rchild != None:
                    queue.append(node.rchild)

    6.2.2 先序遍历历(preorder)

    根节点->左子树->右子树

    def preorder(self, root):
          """递归实现先序遍历"""
          if root == None:
              return
          print (root.elem)
          self.preorder(root.lchild)
          self.preorder(root.rchild)

    6.2.3 中序遍历(inorder)

    左子树->根节点->右子树

    def inorder(self, root):
          """递归实现中序遍历"""
          if root == None:
              return
          self.inorder(root.lchild)
          print (root.elem)
          self.inorder(root.rchild)

    6.2.4 后序遍历(postorder)

    左子树->右子树->根节点

    def postorder(self, root):
          """递归实现后续遍历"""
          if root == None:
              return
          self.postorder(root.lchild)
          self.postorder(root.rchild)
          print (root.elem)

    ps.有中序遍历和先序遍历或后序遍历可以确定一棵树。

  • 相关阅读:
    Ubuntu apt常用命令
    PHP 图片操作(按照指定尺寸压缩,按照比例裁剪)
    Django简介
    浅议SNMP安全、SNMP协议、网络管理学习
    Linux下dmesg命令处理故障和收集系统信息的7种用法
    syslog之三:建立Windows下面的syslog日志服务器
    syslog之二:syslog协议及rsyslog服务全解析
    syslog之一:Linux syslog日志系统详解
    syslog简单配置介绍
    ethtool工具使用实例
  • 原文地址:https://www.cnblogs.com/cirr-zhou/p/9427568.html
Copyright © 2011-2022 走看看