首页 > 其他分享 >数据结构之树(二叉树的存储方式之链表)

数据结构之树(二叉树的存储方式之链表)

时间:2023-11-05 12:11:48浏览次数:43  
标签:node 遍历 TreeNode traversal 链表 之树 二叉树 节点

Java

Java中可以使用链表来实现二叉树的存储。

1. 链表实现二叉树的原理:

   链表是由节点组成的数据结构,每个节点包含一个数据和指向下一个节点的指针。

   在链表中,可以将二叉树的每个节点都看作一个链表节点,同时维护一个指向左子节点的指针和一个指向右子节点的指针。通过这种方式,可以将二叉树的各个节点进行连接,从而实现二叉树的存储。

2. 最佳实践:

   在链表中实现二叉树时,可以定义一个二叉树节点类,该类包含一个数据字段和两个指针字段,分别用于连接左子节点和右子节点。同时,还需要定义一个链表类,该类包含一个指向根节点的指针字段,用于表示二叉树的起始位置。

示例

节点类:表示树的节点

 1 public class TreeNode {
 2     // 数据
 3     int data;
 4     // 左子节点
 5     TreeNode left;
 6     // 右子节点
 7     TreeNode right;
 8     public TreeNode(int data) {
 9         this.data = data;
10         this.left = null;
11         this.right = null;
12     }
13 }

二叉树类:表示树对象

 1 import java.util.LinkedList;
 2 import java.util.Queue;
 3 
 4 /**
 5  * 树类即一个BinaryTree对象代表一个树
 6  */
 7 public class BinaryTree {
 8 
 9     TreeNode root;
10     public BinaryTree(int data) {
11         this.root = new TreeNode(data);
12     }
13     public void insert(int data) {
14         TreeNode newNode = new TreeNode(data);
15         if (root == null) {
16             root = newNode;
17             return;
18         }
19         // 每次都需要遍历,塑造树
20         // 0. 创建树对象
21         Queue<TreeNode> queue = new LinkedList<>();
22         // 1. 根入链
23         queue.offer(root);
24         // 2. 遍历 : 塑造树
25         while (!queue.isEmpty()) {
26             // 2.1 遍历所有节点,判断左右子节点是否为空,顺序先左后右
27             TreeNode current = queue.poll();
28             // 2.2 左子节点为空,当前插入节点作为其左节点
29             if (current.left == null) {
30                 current.left = newNode;
31                 return;
32             } else {
33                 // 2.2 左子节点不为空,入链塑造树
34                 queue.offer(current.left);
35             }
36             // 2.3 遍历所有节点,判断右子节点是否为空
37             //  为空,当前插入节点作为其右子节点
38             if (current.right == null) {
39                 current.right = newNode;
40                 return;
41             } else {
42                 // 不为空,入链,塑造树
43                 queue.offer(current.right);
44             }
45         }
46     }
47 }

测试类

 

public class TreeNode {
    // 数据
    int data;
    // 左子节点
    TreeNode left;
    // 右子节点
    TreeNode right;
    public TreeNode(int data) {
        this.data = data;
        this.left = null;
        this.right = null;
    }
}

  

输出:

Binary Tree traversal:
1 2 4 5 3

  

Python

在 Python 中,可以使用链表来实现二叉树的存储。这种方式通常被称为链表表示法(Linked List Representation)或链表嵌套方式(Linked List Nested Method)。这种表示法相对于数组或列表更灵活,因为它不需要预分配存储空间,并且可以轻松处理不规则的二叉树结构。

1. 二叉树节点的定义

首先,我们需要定义二叉树的节点结构。每个节点需要包括值和两个指向其左子树和右子树的指针。通常,我们使用类来表示节点,如下所示:

class TreeNode:
    def __init__(self, value):
        self.value = value
        self.left = None
        self.right = None

  

创建二叉树

要创建一个二叉树,您可以手动创建节点并连接它们,或者使用一个函数来构建整棵树。下面是一个简单的示例,演示如何创建一个二叉树:

# 创建节点
root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.left.left = TreeNode(4)
root.left.right = TreeNode(5)

在上面的示例中,我们创建了一个包含五个节点的二叉树。

遍历二叉树

一旦创建了二叉树,您可以使用递归或其他遍历算法来访问二叉树的节点。下面是几种常见的二叉树遍历方式:

先序遍历(Preorder Traversal)

先序遍历是一种深度优先遍历方式,它首先访问根节点,然后依次遍历左子树和右子树。下面是先序遍历的示例代码:

def preorder_traversal(node):
    if node:
        print(node.value)
        preorder_traversal(node.left)
        preorder_traversal(node.right)

preorder_traversal(root)

  

中序遍历(Inorder Traversal)

中序遍历也是深度优先遍历方式,它首先遍历左子树,然后访问根节点,最后遍历右子树。下面是中序遍历的示例代码:

def inorder_traversal(node):
    if node:
        inorder_traversal(node.left)
        print(node.value)  
        inorder_traversal(node.right)

inorder_traversal(root)

  

后序遍历(Postorder Traversal)

后序遍历是深度优先遍历方式,它首先遍历左子树,然后遍历右子树,最后访问根节点。下面是后序遍历的示例代码:

def postorder_traversal(node):
    if node:
        postorder_traversal(node.left)
        postorder_traversal(node.right)
        print(node.value)

postorder_traversal(root)

  

示例

class TreeNode:
    def __init__(self, value):
        self.value = value
        self.left = None
        self.right = None


class BinaryTree:

    def __init__(self, value):
        self.root = TreeNode(value)

    def insert(self, data):
        # 创建节点
        insertNode = TreeNode(data)
        if self.root is None:
            self.root = insertNode
        # 存储节点,用于遍历
        arr = [self.root]
        while len(arr) > 0:
            tmp = arr.pop(0)  # pop不指定索引,默认删除最后1个元素
            if tmp.left is None:
                tmp.left = insertNode
                return
            else:
                arr.append(tmp.left)
            if tmp.right is None:
                tmp.right = insertNode
                return
            else:
                arr.append(tmp.right)


'''
前序遍历
'''
def preorder_traversal(node):
    if node:
        print(node.value, end=" ")
        preorder_traversal(node.left)
        preorder_traversal(node.right)


'''
中序遍历
'''
def inorder_traversal(node):
    if node:
        inorder_traversal(node.left)
        print(node.value, end=" ")
        inorder_traversal(node.right)


'''
后序遍历
'''
def postorder_traversal(node):
    if node:
        postorder_traversal(node.left)
        postorder_traversal(node.right)
        print(node.value,end=" ")


tree = BinaryTree(1)
tree.insert(2)
tree.insert(3)
tree.insert(4)
tree.insert(5)
preorder_traversal(tree.root)
print()
inorder_traversal(tree.root)
print()
postorder_traversal(tree.root)

  

输出:

1 2 4 5 3 
4 2 5 1 3 
4 5 2 3 1 

  

最佳实践

在使用链表表示法来实现二叉树时,一些最佳实践包括:

  1. 使用节点类来表示二叉树节点,这可以使代码更加清晰和模块化。

  2. 使用递归算法来遍历二叉树,因为它们通常更简洁和易于理解。

  3. 添加适当的错误处理和条件检查,以避免在访问空节点时出现错误。

  4. 使用合适的数据结构,如栈,来实现非递归遍历算法。

  5. 考虑添加其他属性或方法来处理特定的二叉树操作,如查找、插入和删除节点。

希望这些示例和最佳实践可以帮助您开始使用链表表示法来实现和操作二叉树。链表表示法在处理不规则或动态变化的二叉树结构时非常有用,因为它允许您轻松地连接和重组节点

 

标签:node,遍历,TreeNode,traversal,链表,之树,二叉树,节点
From: https://www.cnblogs.com/allenxx/p/17810385.html

相关文章

  • 101. 对称二叉树
    目录题目题解、前序遍历+递归题目给你一个二叉树的根节点root,检查它是否轴对称。示例1:输入:root=[1,2,2,3,4,4,3]输出:true示例2:输入:root=[1,2,2,null,3,null,3]输出:false题解、前序遍历+递归不仅要判断节点带值的情况,还要考虑空节点位置是否相同clas......
  • 数据结构记录-链表
    1、单链表1、单链表的组成最基本的单链表组成如下:typedefstructLink{charelem;/*数据域*/structLink*next;/*指针域*/}link;/*节点名,每个阶段都是一个Link结构体*/为什么这样的就是链表呢,需要从这个结构体内部组成来看,structLinknext;定义了一个指针变......
  • 07_环形链表
    环形链表给定一个链表的头节点head,返回链表开始入环的第一个节点。如果链表无环,则返回null。如果链表中有某个节点,可以通过连续跟踪next指针再次到达,则链表中存在环。为了表示给定链表中的环,评测系统内部使用整数pos来表示链表尾连接到链表中的位置(索引从0开始)。如......
  • 顺序表和链表
    writeup后面写258.链表去重给定一个键值为整数的单链表L,将键值的绝对值有重复的结点删除:即对任意键值K,只有键值或其绝对值等于K的第一个结点被保留在L中。例如,下面单链表L包含键值21、-15、15、7、-15,如下图(a)所示;去重后的链表L包含键值21、-15、7,如......
  • 数据结构之链表
    1.简介链表(LinkedList)是一种基本的数据结构,用于表示一组元素,这些元素按顺序排列,每个元素都与下一个元素连接。与数组不同,链表的元素不是在内存中连续存储的,而是通过指针来连接的。链表由节点(Node)组成,每个节点包含两个主要部分:数据和指向下一个节点(或上一个节点,如果是双向链表)的......
  • Java面试题:链表-合并两个排序的链表
    描述输入两个递增的链表,单个链表的长度为n,合并这两个链表并使新链表中的节点仍然是递增排序的。示例输入:{1,3,5},{2,4,6}返回值:{1,2,3,4,5,6}原题地址:https://www.nowcoder.com/practice/d8b6b4358f774294a89de2a6ac4d9337代码实现packagecom.example.demo.linked;......
  • Java面试题:链表-反转链表
    问题描述给定一个单链表的头结点pHead(该头节点是有值的,比如在下图,它的val是1),长度为n,反转该链表后,返回新链表的表头。如当输入链表{1,2,3}时,经反转后,原链表变为{3,2,1},所以对应的输出为{3,2,1}。示例输入:{1,2,3}返回值:{3,2,1}原题地址:https://www.nowcoder.com/practice/7......
  • 寻找两个链表相交节点方法(可以是有环链表)
    问题分析:两个链表相交可以分为两个大类,一是两个无环链表相交,二是两个有环链表相交。 无环相交如图:有环相交有两种情况,一种是先相交后成环,如图:另一种是交点有两个,是成环后的交点(入环节点不同) 方法1.判断链表是否有环,返回第一个入环节点。2.判断是否相交3.......
  • 双向链表结构分析
    双向链表描述双向链表也叫双链表,它的每个数据结点都有两个指针,分别指向前驱结点和后继节点,同时有一个数据域来保存数据,双向链表的图示如下:从图片可以看出,双链表的头结点的前驱结点和尾结点的后继结点为空,这一点要注意,对双链表的操作要检查这两种情况。双向链表结构每个数据结......
  • 牛客剑指offer刷题链表篇
    @[TOC]从尾到头打印链表题目输入一个链表的头节点,从尾到头反过来打印出每个节点的值。思路利用栈后进先出的性质实现;代码实现privatestaticvoidprintReverseNode(ListNodehead){if(head==null){return;}ListNodepNode=head;......