class Node:def __init__(self, name, type='dir'):self.name = nameself.type = type   #"dir" or "file"self.children = []self.parent = None# 链式存储def __repr__(self):return self.nameclass FileSystemTree:def __init__(self):self.root = Node("/")self.now = self.rootdef mkdir(self, name):# name 以 / 结尾if name[-1] != "/":name += "/"node = Node(name)self.now.children.append(node)node.parent = self.nowdef ls(self):return self.now.childrendef cd(self, name):# "/var/python/"if name[-1] != "/":name += "/"if name == "../":self.now = self.now.parentreturnfor child in self.now.children:if child.name == name:self.now = childreturnraise ValueError("invalid dir")
tree = FileSystemTree()
tree.mkdir("var/")
tree.mkdir("bin/")
tree.mkdir("usr/")tree.cd("bin/")
tree.mkdir("python/")tree.cd("../")print(tree.ls())
[var/, bin/, usr/]

二叉树

概念:
如果用列表存储,很有地方就会有空着的,浪费空间。因此采用链式存储。

from collections import deque# 二叉树的节点
class BiTreeNode:def __init__(self, data):self.data = dataself.lchild = None   # 左孩子self.rchild = None # 右孩子
a = BiTreeNode("A")
b = BiTreeNode("B")
c = BiTreeNode("C")
d = BiTreeNode("D")
e = BiTreeNode("E")
f = BiTreeNode("F")
g = BiTreeNode("G")e.lchild = a
e.rchild = g
a.rchild = c
c.lchild = b
c.rchild = d
g.rchild = froot = eprint(root.lchild.rchild.data)
C

二叉树的遍历:

# 前序遍历:E在开头
# 先访问左子树,然后访问右子树
def pre_order(root):if root:print(root.data, end=',')pre_order(root.lchild)pre_order(root.rchild)pre_order(root)
E,A,C,B,D,G,F,

# 中序遍历:E在中间
# 先访问左子树,然后访问自己,再访问右子树
def in_order(root):if root:in_order(root.lchild)print(root.data, end=',')in_order(root.rchild)in_order(root)
A,B,C,D,E,G,F,

树(子树)的根在中间。

# 后序遍历
# 先递归左,然后递归右,最后打印自己
def post_order(root):if root:post_order(root.lchild)post_order(root.rchild)print(root.data, end=',')post_order(root)
B,D,C,A,F,G,E,

# 层次遍历
# 一层一层来,从左至右
from collections import dequedef level_order(root):queue = deque()queue.append(root)while len(queue) > 0: # 只要队不空node = queue.popleft()print(node.data, end=',')if node.lchild:queue.append(node.lchild)if node.rchild:queue.append(node.rchild)
level_order(root)
E,A,G,C,F,B,D,

二叉搜索树的概念:

插入:

class BST:def __init__(self, li=None):self.root = Noneif li:for val in li:self.insert_no_rec(val)def insert(self, node, val):# 递归if not node:node = BiTreeNode(val)elif val < node.data:node.lchild = self.insert(node.lchild, val)node.lchild.parent = nodeelif val > node.data:node.rchild = self.insert(node.rchild, val)node.rchild.parent = nodereturn nodedef insert_no_rec(self, val):# 非递归p = self.rootif not p:               # 空树self.root = BiTreeNode(val)returnwhile True:if val < p.data:if p.lchild:p = p.lchildelse:           # 左孩子不存在p.lchild = BiTreeNode(val)p.lchild.parent = preturnelif val > p.data:if p.rchild:p = p.rchildelse:p.rchild = BiTreeNode(val)p.rchild.parent = preturnelse:return
tree = BST([1,4,2,5,3,8,6,9,7])tree.pre_order(tree.root)
print("")
1,4,2,3,5,8,6,7,9,tree.in_order(tree.root)
print("")
1,2,3,4,5,6,7,8,9,tree.post_order(tree.root)
print("")
3,2,7,6,9,8,5,4,1,

对于中序序列,左孩子树都是小的,右孩子树都是大的。所以,中序序列出来一定是由小到大排列的。

查询:


#接上面的代码def query(self, node, val):# 递归if not node:return Noneif node.data < val:return self.query(node.rchild, val)elif node.data > val:return self.query(node.lchild, val)else:return nodedef query_no_rec(self, val):# 非递归p = self.rootwhile p:if p.data < val:p = p.rchildelif p.data > val:p = p.lchildelse:return preturn None
print(tree.query_no_rec(4).data)
4print(tree.query_no_rec(10))
None

删除
有以下三种情况:

不管是左孩子还是右孩子

删除根节点。此时根节点变为35,。

找左子树中最大的数,或者右子树中最小的数。这些数与节点最接近。

# 接上面的代码def __remove_node_1(self, node):# 情况1:node是叶子节点if not node.parent:self.root = Noneif node == node.parent.lchild:  #node是它父亲的左孩子node.parent.lchild = Noneelse:   #右孩子node.parent.rchild = Nonedef __remove_node_21(self, node):# 情况2.1:node只有一个左孩子if not node.parent: # 根节点self.root = node.lchildnode.lchild.parent = Noneelif node == node.parent.lchild:node.parent.lchild = node.lchildnode.lchild.parent = node.parentelse:node.parent.rchild = node.lchildnode.lchild.parent = node.parentdef __remove_node_22(self, node):# 情况2.2:node只有一个右孩子if not node.parent:self.root = node.rchildelif node == node.parent.lchild:node.parent.lchild = node.rchildnode.rchild.parent = node.parentelse:node.parent.rchild = node.rchildnode.rchild.parent = node.parentdef delete(self, val):if self.root:   # 不是空树node = self.query_no_rec(val)if not node: # 不存在return Falseif not node.lchild and not node.rchild: #1. 叶子节点self.__remove_node_1(node)elif not node.rchild:       # 2.1 只有一个左孩子self.__remove_node_21(node)elif not node.lchild:       # 2.2 只有一个右孩子self.__remove_node_22(node)else:   # 3. 两个孩子都有min_node = node.rchildwhile min_node.lchild:min_node = min_node.lchildnode.data = min_node.data# 删除min_nodeif min_node.rchild:self.__remove_node_22(min_node)else:self.__remove_node_1(min_node)
tree.in_order(tree.root)
print("")
1,2,3,4,5,6,7,8,9,tree.delete(4)
tree.in_order(tree.root)
print("")
1,2,3,5,6,7,8,9,

二叉树的搜索效率:
二叉树偏斜时,时间复杂度最差为O(n)。

AVL树

任何节点左右子树的高度差都不能超过1.
平衡因子:记录左右子树的高度差。


AVL树——插入:

沿着左边插入1.然后从1往回找,看是否是平衡树,是否是一个节点路径。只有带颜色的节点平衡可能发生变化。
相关网站:树结构图示

看2是否平衡。左1,右0.平衡往下找。

4:左边2,右边1.相差1以内,平衡。

6。左3右1。不平衡,

通过旋转,使其平衡。此时,左边的子树是平衡的。


不平衡的情况:
(同性则异,异性则同)
左左——右旋

右右——左旋

右左——右旋-左旋


左右——左旋-右旋

在插入的时候,从插入的节点到根节点,往回找。找到第一个节点的平衡因子是±2的,然后根据以上四种情况,进行旋转。

旋转实现代码:

插入实现代码:

AVL树的应用:

二叉树扩展应用——B树
AVL树是二叉树,B树是多叉树。

Python数据结构与算法笔记(八):数据结构——树,二叉树和AVL树相关推荐

  1. DSA 经典数据结构与算法 学习心得和知识总结(四) | AVL树

    AVL树 从BST的角度看AVL AVL的定义及性质 AVL树的结构定义 AVL树的旋转算法 左左情况---右旋 右右情况---左旋 左右情况---左右旋 右左情况---右左旋 AVL树的遍历操作 A ...

  2. 软考-嵌入式系统设计师:程序设计、数据结构和算法:笔记(八)]

    大家不要只收藏不关注呀,哪怕只是点个赞也可以呀!

  3. 【数据结构和算法笔记】:数据结构概述

    数据结构包括数据的逻辑结构,数据的存储结构和数据的运算 逻辑结构包括线性结构和非线性结构(集合,线性结构,树形结构,图形结构) 线性结构:元素关系一对一,第一个节点没有前驱节点,其余每一个节点只有一个 ...

  4. 数据结构源码笔记(C语言):B树的相关运算算法

    //B树的相关运算算法#include<stdio.h> #include<malloc.h>#define MAXM 10//定义B树最大的阶数 typedef int Ke ...

  5. 数据结构源码笔记(C语言):Huffman树字符编码

    #include <stdio.h> #include<string.h> #define N 10 /*待编码字符的个数,即树中叶结点的最大个数*/ #define M 2* ...

  6. 数据结构与算法笔记(十六)—— 二叉搜索树

    一.二叉搜索树定义 二叉搜索树(Binary Search Tree),又名二叉排序树(Binary Sort Tree). 二叉搜索树是具有有以下性质的二叉树: 若左子树不为空,则左子树上所有节点的 ...

  7. 数据结构与算法笔记(青岛大学王卓老师视频)

    写在前面的话: 因为在学习数据结构之前,学习过一年的算法,所以有一些基础,一些我觉得 没必要的代码或知识就没写上,记得多是一些知识点,写的可能对于别人来说 很难接受,望谅解.我学习算法是在Acwing ...

  8. 数据结构与算法笔记 - 绪论

    数据结构与算法笔记 - 绪论 1. 什么是计算 2. 评判DSA优劣的参照(直尺) 3. 度量DSA性能的尺度(刻度) 4. DSA的性能度量的方法 5. DSA性能的设计及其优化 x1. 理论模型与 ...

  9. 数据结构与算法笔记(十五)—— 散列(哈希表)

    一.前沿 1.1.直接寻址表 当关键字的全域U比较小时,直接寻址是一种简单而有效的技术.假设某应用要用到一个动态集合,其中每个元素都有一个取自全域U={0,1,-,m-1)的关键字,此处m是一个不很大 ...

  10. python的基本数据结构_Python学习笔记——基本数据结构

    列表list List是python的一个内置动态数组对象,它的基本使用方式如下: shoplist = ['apple', 'mango', 'carrot', 'banana'] print 'I ...

最新文章

  1. TLS1.3 协议的Golang 实现——ClientHello
  2. [转]Display PDF within web browser using MVC3
  3. vue2.0 #$emit,$on的使用
  4. React学习途径和资料分享
  5. python生成词云代码无错窗口空框_10分钟教你用Python生成属于自己的词云图
  6. WINDOWS下DOCKER安装后卡在boot2docker.iso无法启动
  7. 数据挖掘之模型选择和融合
  8. SpringBoot读取外部配置文件的方法
  9. 计算机上机单招试题及答案,全国高职单招计算机类模拟试卷考卷及答案
  10. 【注意力+推荐系统】Attention!当推荐系统遇见注意力机制
  11. Python的中文处理
  12. 这10本豆瓣高分经典数学书,果断收藏!
  13. java instant_Java Instant类
  14. excel打不开html超链接,mac excel打不开超链接
  15. gets,fgetc,fgets,getc,getchar,putc,fputc,putchar,puts,fputs函数详讲
  16. BMC-IPMB specification
  17. python字母对应序号_python获取字母在字母表对应位置的几种方法及性能对比较
  18. 全球及中国网络漫画行业发展前景及未来趋势调研报告2021年版
  19. Fully Convolutional Networks for Semantic Segmentation全文翻译和阅读
  20. 关于无法修改本地Hosts文件解决办法

热门文章

  1. Java中的Class类
  2. 【Unity3d】【项目学习心得】从资源服务器下载资源(二)
  3. java可以实现agv调度吗_AGV路线优化及实时调度
  4. mysql开发平台_搭建mysql编程平台
  5. 我安装java了_我安装了JAVA为什么.......
  6. android httppost
  7. jsfl读取xml,图片,并生成swf
  8. 东大14春学期《计算机应用基础》在线作业1,东大18春学期《计算机应用基础》在线作业...
  9. idea中springBoot项目修改html之类的文件后服务不自动更新
  10. el-table click事件多次触发_JavaScript从零开始——DOM事件编程(1)