树、图的构造与遍历和图的最小生成树

1.二叉树

1.1 二叉树类的实现

首先构造节点类,它的属性包括元素、左孩子、右孩子。然后构造二叉树类,它的属性有根节点。

class Node(object):
    def __init__(self, item):
        self.elem = item
        self.lchild = None
        self.rchild = None
class Tree(object):
    '''二叉树类, 需要指定一个根节点'''
    def __init__(self):
        self.root = None

1.2 二叉树添加元素

首先将新元素构造为一个新的节点类的实例,然后根据广度优先原则首先找到添加节点的位置,添加节点。

# 伪代码如下
    def add(self, item):
        新节点node = 新节点类的实例
        如果根节点为空,self.root = node.

        queue = [self.root] # 用队列来存放遍历的节点
        当队列不为空:
            当前节点 = queue 队首的节点,并在queue中删除该节点
            如果当前节点的左孩子为空:
                新节点赋值给当前节点左孩子
            否则:
                将当前节点的左孩子加入到队列中
            如果当前节点的右孩子为空:
                新节点赋值给当前节点右孩子
            否则:
                将当前节点的右孩子加入到队列中
    def add(self, item):
            node = Node(item)

            if self.root is None:
                self.root = node
                return

            queue = [self.root] # 用来存放要处理的东西
            while queue:
                cur_node = queue.pop(0)
                if cur_node.lchild is None:
                    cur_node.lchild = node
                    return
                else:
                    queue.append(cur_node.lchild)
                if cur_node.rchild is None:
                    cur_node.rchild = node
                    return
                else:
                    queue.append(cur_node.rchild)

1.3 二叉树的广度优先遍历

广度优先遍历即先遍历兄弟节点,再遍历孩子节点。

# 伪代码
    def breadth_travel(self):
        如果根为空,直接返回
        queue = [self.root] # 将根节点添加到队列
        当队列不为空:
            当前节点 = queue 队首的节点,并在queue中删除该节点
            打印出该节点的元素值
            
            如果当前节点的左孩子非空:
                将当前节点的左孩子添加到队列中
            如果当前节点的右孩子非空:
                将当前节点的右孩子添加到队列中
    def breadth_travel(self):
            if self.root is None:
                return
            queue = [self.root]
            while queue:
                cur_node = queue.pop(0)
                print(cur_node.elem, end=' ')
                if cur_node.lchild is not None:
                    queue.append(cur_node.lchild)
                if cur_node.rchild is not None:
                    queue.append(cur_node.rchild)

1.4 二叉树的深度优先遍历

深度优先遍历即先遍历孩子节点,再遍历兄弟节点。这里实现的深度优先遍历是“中序遍历”,即“左孩子——根节点——右孩子”。运用递归的思想,只需不断调用自身函数就能遍历完。

# 伪代码
# 调用时需要传入二叉树的根节点,不断递归调用
    def preorder_travel(self, node):
        如果node为空,直接返回
        打印node的元素值
        preorder_travel(self, node的左孩子)
        preorder_travel(self, node的右孩子)
    def preorder_travel(self, node):
        if node is None:
            return
        print(node.elem, end=' ')
        self.preorder_travel(node.lchild)
        self.preorder_travel(node.rchild)

2.图

2.1 图的实现

图作为数据结构由 “字典” 实现,字典的键为“点”,值为“与键相邻的点”。

class Gragh():
    def __init__(self,sequense):
        '''sequense是一个集合,key是点,value是与key相连接的点'''
        self.sequense = sequense 

在实例化一个图的时候,需要传入如下所示的集合,表示 'A' 与 'B', 'C'相邻。

sequense = {'A': ['B'],
             'B': ['C', 'D'],
             'C': ['E'],
             'D': [],
             'E': ['A']}

2.2 图的广度优先遍历

图的遍历需要指定一个节点,将图转化为以这个节点为根的树,沿着树的广度进行遍历。

(1)顶点v入队列。
(2)当队列非空时则继续执行,否则算法结束。
(3)出队列取得队头顶点v;访问顶点v并标记顶点v已被访问。
(4)查找顶点v的第一个邻接顶点col。
(5)若v的邻接顶点col未被访问过的,则col入队列。
(6)继续查找顶点v的另一个新的邻接顶点col。
(7)直到顶点v的所有未被访问过的邻接点处理完。

    def BFS(self, source):
        frontiers = [source] # 前驱节点
        traveled = [source] # 遍历过的节点
        
        while frontiers:
            nexts = []
            for frontier in frontiers:
                for cur in self.sequense[frontier]:
                    if cur not in traveled:
                        traveled.append(cur)
                        nexts.append(cur)
            frontiers = nexts # 更新一层前驱节点
        
        return traveled
    

2.3 图的深度优先遍历

指定一个节点,将图转化为以这个节点为根的树,沿着树的深度进行遍历。

(1)访问初始顶点v并标记顶点v已访问。
(2)查找顶点v的第一个邻接顶点w。
(3)若顶点v的邻接顶点w存在,则继续执行;否则回溯到v,再找v的另外一个未访问过的邻接点。
(4)若顶点w尚未被访问,则访问顶点w并标记顶点w为已访问。
(5)继续查找顶点w的下一个邻接顶点wi,如果v取值wi转到步骤(3)。
(6)直到所有顶点访问完。

       def DFS(self, source):
        traveled = []
        stack = [source]
        
        while stack:
            cur = stack.pop()
            if cur not in traveled:
                traveled.append(cur)
            for next_adj in self.sequense[cur]:
                if next_adj not in traveled:
                    stack.append(next_adj)
        return traveled

3.图的最小生成树

所有节点分成两个group,一个为已经选取的selected_node(用python中的list实现),一个为candidate_node。

首先任取一个节点加入到selected_node,然后遍历头节点在selected_node,尾节点在candidate_node的边,选取符合这个条件的边里面权重最小的边,加入到最小生成树,选出的边的尾节点加入到selected_node,并从candidate_node删除。直到candidate_node中没有备选节点。

在这里的图的每条边是有权重的,所以需要实现一个新的图的类,不同于 章节2 中通过点与点的临接关系确定图,而是用邻接矩阵描述图。

class Graph(object):
    def __init__(self, maps):
        self.maps = maps
        self.nodenum = self.get_nodenum()
        self.edgenum = self.get_edgenum()
 
    def get_nodenum(self):
        return len(self.maps)
 
    def get_edgenum(self):
        count = 0
        for i in range(self.nodenum):
            for j in range(i):
                if self.maps[i][j] > 0 and self.maps[i][j] < 9999:
                    count += 1
        return count
 
    def prim(self):
        res = []
        if self.nodenum <= 0 or self.edgenum < self.nodenum-1:
            return res
        res = []
        seleted_node = [0]
        candidate_node = [i for i in range(1, self.nodenum)]
        
        while len(candidate_node) > 0:
            begin, end, minweight = 0, 0, 9999
            for i in seleted_node:
                for j in candidate_node:
                    if self.maps[i][j] < minweight:
                        minweight = self.maps[i][j]
                        begin = i
                        end = j
            res.append([begin, end, minweight])
            seleted_node.append(end)
            candidate_node.remove(end)
        return res

构建一个如下图所示的图的实例

图结构
max_value = 9999
row0 = [0,7,max_value,max_value,max_value,5]
row1 = [7,0,9,max_value,3,max_value]
row2 = [max_value,9,0,6,max_value,max_value]
row3 = [max_value,max_value,6,0,8,10]
row4 = [max_value,3,max_value,8,0,4]
row5 = [5,max_value,max_value,10,4,0]
maps = [row0, row1, row2,row3, row4, row5]
graph = Graph(maps)

print(graph.prim())
输出为:[[0,5,5], [5,4,4], [4,1,3], [4,3,8], [3,2,6]]
其中每一项前两位为点,第三位为这两个点连边的权重
最小生成树为:0——5——4——1
                 4——3——2
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容

  • 1 概述 图是数据结构中最复杂的形式,也是最烧脑的结构。无数的牛人乐此不疲地钻研,然而,时至今日,依然有很多问题等...
    CodingTech阅读 2,288评论 0 8
  • 1)这本书为什么值得看: Python语言描述,如果学的Python用这本书学数据结构更合适 2016年出版,内容...
    孙怀阔阅读 12,428评论 0 15
  • 1. 图的定义和基本术语 线性结构中,元素仅有线性关系,每个元素只有一个直接前驱和直接后继;树形结构中,数据元素(...
    yinxmm阅读 5,426评论 0 3
  • 前几天妹妹打电话过来说,姐姐,我们这个专业在学校不招人了,我应该在学点啥,要不要考教师证书啥的?我沉默了很久...
    雁攸宁的小九九阅读 130评论 0 1
  • 区块链钱包相关资源记录 1.1 Bitcoin 1.1.1 RPC Original Bitcoin client...
    xxzsxxzs阅读 1,990评论 0 0