javascript/js实现 排序二叉树数据结构 学习随笔

二叉树是一种数据结构。其特点是:

1.由一系列节点组成,具有层级结构。每个节点的特性包含有节点值、关系指针。节点之间存在对应关系。

2.树中存在一个没有父节点的节点,叫做根节点。树的末尾存在一系列没有子节点的节点,称为叶子节点。其他可以叫做中间节点。

3.树的根节点位于第一层,层级数越大,节点位置越深,层级数也叫做树高。

排序二叉树为二叉树的一种类型,其特点是:

1.节点分为左右子树。

2.在不为空的情况下,左子树子节点的值都小于父节点的值。

3.在不为空的情况下,右子树子节点的值都大于父节点的值。

4.每个节点的左右子树都按照上述规则排序。

如图:

(打错字了..)

js代码来实现上述数据结构:

1.节点用对象来描述,节点特性用对象属性来描述。

1 class Node {
2   constructor(key) {
3     this.key = key;// 节点值
4     this.left = null;// 左指针
5     this.right = null;// 右指针
6   }
7 }

2.二叉树结构用对象来描述。

 1 // 二叉树
 2 class BinaryTree {
 3   constructor() {
 4     this.root = null;// 根节点
 5   }
 6   insert(key) {// api--插入
 7     const newNode = new Node(key);
 8     if (this.root === null) {// 设置根节点
 9       this.root = newNode;
10     }
11     method.insertNode(this.root, newNode);
12   }
13 }

相关方法:

 1 // method
 2 method = {
 3   insertNode(root, newNode) {
 4     if (newNode.key < root.key) {// 进入左子树
 5       if (root.left === null) {// 左子树为空
 6         root.left = newNode;
 7       } else {// 左子树已存在
 8         method.insertNode(root.left, newNode);
 9       }
10     } else if (newNode.key > root.key) {// 进入右子树
11       if (root.right === null) {// 右子树为空
12         root.right = newNode;
13       } else {// 右子树已存在
14         method.insertNode(root.right, newNode);
15       }
16     }
17   }
18 };

具体用法:

1 // 实例化二叉树
2 const binaryTree = new BinaryTree();
3
4 // key值
5 const keys = [19, 8, 15, 24, 45, 12, 5];
6
7 // 生成排序二叉树
8 keys.forEach(key => binaryTree.insert(key));

结果:

排序二叉树的遍历:

一、中序遍历

(1)以上图为例,中序遍历顺序为: 5 - 8 - 12 - 15 - 19 - 24 - 45。

(2)总是先遍历左子树,然后访问根节点,接着遍历右子树。

代码实现:

 1 class BinaryTree {
 2   ...
 3   // callback为访问节点时执行的操作
 4   inorderTraversal(callback) {// api--中序遍历
 5     method.inorderTraversalNode(this.root, callback);
 6   }
 7 }
 8
 9 method = {
10   ...
11
12   inorderTraversalNode(node, callback) {
13     if (node) {// 当前节点
14       method.inorderTraversalNode(node.left, callback);// 遍历左子树
15       callback(node);// 访问节点
16       method.inorderTraversalNode(node.right, callback);// 遍历右子树
17     }
18   },
19 };
20
21 // 中序遍历
22 binaryTree.inorderTraversal(node => console.log(node.key));
1 // key值
2 const keys = [19, 8, 15, 24, 45, 12, 5];

输入结果:5 - 8 - 12 - 15 - 19 - 24 - 45

二、前序遍历

(1)以上图为例,前序遍历顺序为: 19 - 8 - 5 - 15  - 12 - 24 - 45。

(2)总是先访问根节点,然后遍历左子树,接着遍历右子树。

代码实现:

 1 class BinaryTree {
 2   ...
 3   preOrderTraversal(callback) {// api--前序遍历
 4     method.preOrderTraversalNode(this.root, callback);
 5   }
 6 }
 7
 8 method = {
 9   ...
10   preOrderTraversalNode(node, callback) {
11     if (node) {// 当前节点
12       callback(node);// 访问节点
13       method.preOrderTraversalNode(node.left, callback);// 遍历左子树
14       method.preOrderTraversalNode(node.right, callback);// 遍历右子树
15     }
16   }
17 };
18
19 // 前序遍历
20 binaryTree.preOrderTraversal(node => console.log(node.key));
1 // key值
2 const keys = [19, 8, 15, 24, 45, 12, 5];

输入结果:19 - 8 - 5 - 15  - 12 - 24 - 45

三、后序遍历

(1)以上图为例,后序遍历顺序为: 5 - 12 - 15 - 8  - 45 - 24 - 19。

(2)先遍历左子树,接着遍历右子树,最后访问根节点。

代码实现:

 1 class BinaryTree {
 2   ...
 3   postOrderTraversal(callback) {// api--后序遍历
 4     method.postOrderTraversalNode(this.root, callback);
 5   }
 6 }
 7
 8 method = {
 9   ...
10   postOrderTraversalNode(node, callback) {
11     if (node) {// 当前节点
12       method.postOrderTraversalNode(node.left, callback);// 遍历左子树
13       method.postOrderTraversalNode(node.right, callback);// 遍历右子树
14       callback(node);// 访问节点
15     }
16   }
17 };
18
19 // 后序遍历
20 binaryTree.postOrderTraversal(node => console.log(node.key));
1 // key值
2 const keys = [19, 8, 15, 24, 45, 12, 5];

输入结果:5 - 12 - 15 - 8  - 45 - 24 - 19

排序二叉树的查找:

(1)查找最大值。根据排序二叉树的特点,右子树的值都大于父节点的值。只需要进入节点的右子树查找,当某个节点的右子树为空时,该节点就是最大值节点。

代码实现:

 1 class BinaryTree {
 2   ...
 3   max() {
 4     return method.maxNode(this.root);
 5   }
 6 }
 7
 8 method = {
 9   ...
10   maxNode(node) {
11     if (node) {
12       while(node.right !== null) {// 右子树不为空时
13         node = node.right;
14       }
15       return node.key;
16     }
17     return null;
18   }
19 };
1 // key值
2 const keys = [19, 8, 15, 24, 45, 12, 5];

结果:

(2)查找最小值。根据排序二叉树的特点,左子树的值都小于父节点的值。只需要进入节点的左子树查找,当某个节点的左子树为空时,该节点就是最小值节点。

代码实现:

 1 class BinaryTree {
 2   ...
 3   min() {
 4     return method.minNode(this.root);
 5   }
 6 }
 7
 8 method = {
 9   ...
10   minNode(node) {
11     if (node) {
12       while(node.left!== null) {// 左子树不为空时
13         node = node.left;
14       }
15       return node.key;
16     }
17     return null;
18   }
19 };
1 // key值
2 const keys = [19, 8, 15, 24, 45, 12, 5];

结果:

(3)查找给定值。在排序二叉树中查找有没有节点对应的值与给定值相同。

根据排序二叉树的特点,比较给定值与节点值,小于时进入节点左子树。大于时进入节点右子树。等于时返回真。层层对比,最后如果子树为空,则表示没有找到。

代码实现:

 1 class BinaryTree {
 2   ...
 3   search(key) {
 4     return method.searchNode(this.root, key);
 5   }
 6 }
 7
 8 method = {
 9   ...
10   searchNode(node, key) {
11     if (node === null) {// 没有找到
12       return false;
13     }
14     if (key < node.key) {// 进入左子树
15       return method.searchNode(node.left, key);
16     } else if (key > node.key) {// 进入右子树
17       return method.searchNode(node.right, key);
18     } else {// 找到了
19       return true;
20     }
21   }
22 };
1 // key值
2 const keys = [19, 8, 15, 24, 45, 12, 5];

结果:

排序二叉树的删除:

当删除的节点为叶子节点时,直接把叶子节点设置成空。如图:删除值为5的节点。

原:

现:

当删除的节点存在左子树时,把父节点的关系指针直接指向左子树。如图:删除值为15的节点。存在右子树时同理。

原:

现:

当节点存在左右子树时,先去右子树里找到最小值,然后用最小值替换节点值,最后进入右子树删除最小值对应的节点。如图:删除值为8的节点。

原:

现:

代码实现:

 1 class BinaryTree {
 2   ...
 3   remove(key) {
 4     this.root = method.removeNode(this.root, key);
 5   }
 6 }
 7
 8 method = {
 9   ...
10   removeNode(node, key) {
11     if(node === null) {// 没有找到值对应的节点
12       return null;
13     }
14     if (key < node.key) {// 给定值小于当前节点值
15       node.left = method.removeNode(node.left, key);
16       return node;
17     } else if (key > node.key) {// 给定值大于当前节点值
18       node.right = method.removeNode(node.right, key);
19       return node;
20     } else {// 找到给定值对应的节点
21       if (node.left === null && node.right === null) {// 节点为叶子节点
22         node = null;
23         return node;
24       }
25
26       if (node.left === null) {// 节点存在右子树
27         node = node.right;
28         return node;
29       } else if (node.right === null) {// 节点存在左子树
30         node = node.left;
31         return node;
32       }
33
34       // 节点存在左右子树时,先去右子树里找到最小值,然后用最小值替换节点值,最后进入右子树删除最小值对应的节点。
35       const minKey = method.minNode(node.right);
36       node.key = minKey;
37       method.removeNode(node.right, minKey);
38       return node;
39     }
40   }
41 };

结果:

累死我了。。。

原文地址:https://www.cnblogs.com/caimuguodexiaohongmao/p/11123933.html

时间: 2024-11-29 11:10:52

javascript/js实现 排序二叉树数据结构 学习随笔的相关文章

C语言 排序算法 - 数据结构学习笔记

/**  功能:     排序   *日期:     2017年9月24日   *作者:     yzh   *开发环境:  QT   **/ #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_STACK_LENGTH 100     //非递归快速排序调用栈 #define MAX_LENGTH 20            //数组最大值 //对于数值型 keyType #de

c数据结构学习随笔

#include <stdio.h> #include <stdlib.h> #include "PublicDS.h" #include<Windows.h> typedef struct stack{ int top = -1; int maxSize = 100; //用于存放二进制位 int *data = (int *)malloc(100 * sizeof(int)); int pop(){ if (!isEmpty()) return

数据结构与算法系列研究五——树、二叉树、三叉树、平衡排序二叉树AVL

树.二叉树.三叉树.平衡排序二叉树AVL 一.树的定义 树是计算机算法最重要的非线性结构.树中每个数据元素至多有一个直接前驱,但可以有多个直接后继.树是一种以分支关系定义的层次结构.    a.树是n(≥0)结点组成的有限集合.{N.沃恩}     (树是n(n≥1)个结点组成的有限集合.{D.E.Knuth})      在任意一棵非空树中:        ⑴有且仅有一个没有前驱的结点----根(root).        ⑵当n>1时,其余结点有且仅有一个直接前驱.         ⑶所有结

01-(2)数据结构- 一步一步写算法(之之排序二叉树)

前面我们讲过双向链表的数据结构.每一个循环节点有两个指针,一个指向前面一个节点,一个指向后继节点,这样所有的节点像一颗颗珍珠一样被一根线穿在了一起.然而今天我们讨论的数据结构却有一点不同,它有三个节点.它是这样定义的: [cpp] view plain copy typedef struct _TREE_NODE { int data; struct _TREE_NODE* parent; struct _TREE_NODE* left_child; struct _TREE_NODE* rig

数据结构学习之第7章 树和二叉树

数据结构学习之第7章 树和二叉树 0x7.1.1 树的基本概念 ?1.树的定义 ? 树是由n(n>=0)个结点(或元素)组成的有限集合(记为T) ? 如果n>0,这n个结点中有且仅有一个结点作为树的根结点,简称为根,其余结点可分为m(m>=0)个互不相交的有限集\[T_{1}T_{2}\cdots T_{m}\],其中每个子集又是一棵符合定义的子树,称为根结点的子树. 知识点:由树的定义我们可以看出来树的结构是递归的 ?2.树的逻辑表示法 ? 1.树形表示法 ? 2.文氏图表示法 ? 3

JavaScript ES6 数组新方法 学习随笔

JavaScript ES6 数组新方法 学习随笔 新建数组 var arr = [1, 2, 2, 3, 4] includes 方法 includes 查找数组有无该参数 有返回true var includes = arr.includes(2) map方法 map 遍历处理返回新数组 原数组不会改变 var map = arr.map(function (item) { return ++item }) reduce方法 reduce 遍历处理数组返回结果 prev与next中间的符号以

linux基础学习随笔【根本没有排序哈】

直接整:init 3 5 6 0;init 3代表切换到字符界面,5代表切换到图形界面:6表示重启,等同于reboot:0表示关机=poweroff:改主机名:hostnamectl set-hostname centos7.localdomain;[记不住,TAB键补全]查看操作系统linux版本:cat /etc/centos-release;或者通过安装lsb_release -a ;查看内核版本: uname -rlscpu 查看CPU使用情况:lsblk查看硬盘:free - h查看内

算法学习之查找(顺序、二分法、排序二叉树以及 Hash 表)

[摘要]查找--用关键字标识一个数据元素,查找时根据给定的某个值,在表中确定一个关键字的值等于给定值的记录或数据元素.在计算机中进行查找的方法是根据表中的记录的组织结构确定的.查找功能数据处理的一个基本功能.数据查找并不复杂,但是如何实现数据又快又好地查找呢?前人在实践中积累的一些方法,值得我们好好学些一下.我们假定查找的数据唯一存在,数组中没有重复的数据存在. 1. 顺序查找 设想有一个1M的数据,我们如何在里面找到我们想要的那个数据.此时数据本身没有特征,所以我们需要的那个数据可能出现在数组

数据结构之二叉树 树结构练习——排序二叉树的中序遍历 (排序建树+中序遍历)

树结构练习——排序二叉树的中序遍历 Time Limit: 1000MS Memory limit: 65536K 题目描述 在树结构中,有一种特殊的二叉树叫做排序二叉树,直观的理解就是——(1).每个节点中包含有一个关键值 (2).任意一个节点的左子树(如果存在的话)的关键值小于该节点的关键值 (3).任意一个节点的右子树(如果存在的话)的关键值大于该节点的关键值.现给定一组数据,请你对这组数据按给定顺序建立一棵排序二叉树,并输出其中序 遍历的结果. 输入 输入包含多组数据,每组数据格式如下.