Rumah hujung hadapan web tutorial js 使用JavaScript如何实现二叉树遍历

使用JavaScript如何实现二叉树遍历

Jun 19, 2018 pm 04:02 PM
javascript Pokok binari takrifan Cari Melintasi

这篇文章主要介绍了JavaScript实现二叉树定义、遍历及查找的方法,结合实例形式较为详细的分析了二叉树的相关概念及javascript构建二叉树、遍历、查找二叉树的常用操作技巧,需要的朋友可以参考下

本文实例讲述了JavaScript实现二叉树定义、遍历及查找的方法。分享给大家供大家参考,具体如下:

二叉树(binary tree)

在写这篇文章之前说一下数据结构和算法这个系列,这个系列包含了很多东西,比如啥子排序,线性表,广义表,树,图这些大家都是知道的,但是这些东西我们学了之后工作中能用到的又有多少呢,据我所知绝大部分公司,一线码农,屌丝,程序猿是用不到这些东西,既然这样为啥子我还要强调这个系列呢,本人觉得算法和数据结构是程序的基本功,前提想脱离一线码农,普通程序猿行列,说得通俗一点就是让自己变的更牛逼。其次语言都是想通的,只要是掌握了一门语言学习其他语言就如同顺水推舟,不费一点力气。另外还有一点就是我会一直把这个系列写下去, 虽然网上一搜一大筐,已经写烂了,但是我写作的目的有两个,第一和大家分享, 第二可以让自己更深入的理解。好了,其他的不多说了,最近复习了一下二叉树, 就先写这个,后面会依次的加上排序, 线性表,广义表。。。。等等

二叉树

一说到二叉树我们肯定会问,什么是二叉树,二叉树是个啥子东东,拿来有啥子用嘛,我们为啥子要学习它嘛? 如果当初你在学习二叉树的时候你没有问过自己这些问题,那么你对它的了解也仅仅也只是了解。那我们现在来说说什么是二叉树,二叉树就是一种数据结构, 它的组织关系就像是自然界中的树一样。官方语言的定义是:是一个有限元素的集合,该集合或者为空、或者由一个称为根的元素及两个不相交的、被分别称为左子树和右子树的二叉树组成。至于为啥子要学习它,妈妈总是说,孩子,等你长大了就明白了。

二叉树的性质

性质1:二叉树第i层上的节点数目最多为2i-1(i≥1);
性质2:深度为k的二叉树至多有2k-1个结点(k≥1)。
性质3: 在任意-棵二叉树中,若叶子结点(即度为0的结点)的个数为n0,度为1的结点数为n1,度为2的结点数为n2,则no=n2+1。

二叉树的存储结构与构建

二叉树的存储方式有两种,一种顺序存储,比如:
var binaryTree = ['a', 'b', 'c', 'd', 'e', 'f', 'h', 'i']; 这就是一颗二叉树,假设binaryTree[i]是二叉树的一个节点,那么它的左孩子节点 leftChild = binaryTree[i*2+1]那么相应的右孩子节点 rightChild = binaryTree[i*2+2]; 一般情况下顺序存储的这种结构用的较少,另外一种存储方式就是链式存储,下面我会用代码来详细描述二叉树式结构的构建与存储方式,构建二叉树也有两种方式一种是递归方式构建,这种很简单,另一种是非递归方法构建,这种呢相对于前一种复杂一点点,不过也不用担心,我在代码中加上详细的注释,一步一步的走下去。我们现在就以26个英文字母来构建二叉树

复制代码 代码如下:

var charecters = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];

在构建二叉树之前我们会用到一个节点对象,节点对象如下:(注意:关于javascript的面向对象,原型,语法特点我会放在javascript语言知识点这个系列)

/*
 *二叉树的节点对象
 */
function Node() {
  this.text = '';      //节点的文本
  this.leftChild = null;  //节点的左孩子引用
  this.rightChild = null;  //节点右孩子引用
}
Salin selepas log masuk

递归构建二叉树

在构建好二叉树节点之后我们紧接着用递归来构建二叉树

var charecters = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
function buildTree(node, i) {
    var leftIndex = 2*i+1,             //左孩子节点的索引
      rightIndex = 2*i+2;             //右孩子节点的索引
    if(leftIndex < charecters.length) {       //判断索引的长度是否超过了charecters数组的大小
      var childNode = new Node();         //创建一个新的节点对象
      childNode.text = charecters[leftIndex];   //给节点赋值
      node.leftChild = childNode;         //给当前节点node加入左孩子节点
      buildTree(childNode, leftIndex);      //递归创建左孩子
    }
    if(rightIndex < charecters.length) {      //下面注释参照上面的构建左孩子的节点
      var childNode = new Node();
      childNode.text = charecters[rightIndex];
      node.rightChild = childNode;
      buildTree(childNode, rightIndex);
    }
}
//下面构造二叉树
var node = new Node();
node.text = charecters[0];
buildTree(node, 0);  //索引i是从0开始构建
Salin selepas log masuk

非递归构建二叉树

下面是以非递归方式构建二叉树:

var root;
function createBinaryTree() {
    var len = charecters.length,        //数组的长度
      index = 0,               //索引从0开始
      nodes = new Array();          //创建一个临时数组,用于存放二叉树节点
    //循环创建二叉树节点存放到数组中
    for (var i = 0 ; i < charecters.length ; i++) {
      var node = new Node();
      node.text = charecters[i];
      nodes.push(node);
    }
    //循环建立二叉树子节点的引用
    while(index < len) {
      var leftIndex = 2*index+1,       //当前节点左孩子索引
        rightIndex = 2*index+2;       //当前节点右孩子索引
      //给当前节点添加左孩子
      nodes[index].leftChild = nodes[leftIndex];
      //给当前节点添加右孩子
      nodes[index].rightChild = nodes[rightIndex];
      index++;
    }
    root = nodes[0];
}
Salin selepas log masuk

二叉树的三种遍历

好了,现在我们已经成功构建了二叉树的链式结构,在构建了二叉树的链式结构后我们进入二叉树的最基本的遍历了,遍历有三种最基本的遍历,我不说想必大家都知道,先序遍历,中序遍历和后续遍历。虽然这三种遍历递归方式都比较简单,但非递归方式就不是那么容易了,当时我在实现的时候都卡了半天,真的是说起来容易做起来难啊,在实现遍历前我们首先要来实现的是栈,因为在非递归遍历的时候会用到栈,那到底什么是栈呢,这里我就简单介绍下吧,有兴趣的朋友可以去维基百科有权威的定义,栈和队列也是一种数据结构,栈存放数据的时候是先进先出,而队列是先进后出。

实现栈的对象

下面用javascript来实现栈的对象

function Stack() {
    var stack = new Array();        //存放栈的数组
    //压栈
    this.push = function(o) {
      stack.push(o);
    };
    //出栈
    this.pop = function() {
      var o = stack[stack.length-1];
      stack.splice(stack.length-1, 1);
      return o;
    };
    //检查栈是否为空
    this.isEmpty = function() {
      if(stack.length <= 0) {
        return true;
      }
      else {
        return false;
      }
    };
}
//使用方式如下
var stack = new Stack();
stack.push(1);    //现在栈中有一个元素
stack.isEmpty();   //false , 栈不为空
alert(stack.pop()); //出栈, 打印1
stack.isEmpty();   //true, 此时栈为空,因为在调用了stack.pop()之后元素出栈了,所以为空
Salin selepas log masuk

1. 先序遍历

在实现了栈对象以后我们首先来进行先序遍历的递归方式

function firstIteration(node) {
    if(node.leftChild) {          //判断当前节点是否有左孩子
      firstIteration(node.leftChild);  //递归左孩子
    }
    if(node.rightChild) {         //判断当前节点是否有右孩子
      firstIteration(node.rightChild);  //递归右孩子
    }
}
//递归遍历二叉树
firstIteration(root);
Salin selepas log masuk

先序遍历的非递归方式

上面的代码大家可以在firstIteration()方法中加个alert()函数来验证是否正确。那么下面就要说说先序遍历的非递归方式,遍历思想是这样的:先访问根节点在访问左节点, 最后访问右节点。从根节点一直往下访问找左孩子节点,直到最后一个左孩子节点(将这条路径保存到栈中),然后再访问最后一个左孩子的兄弟节点(右孩子节点),之后回溯到上一层(将栈中的元素取出 就是出栈),又开始从该节点(回溯到上一层的节点)一直往下访问找左孩子节点... 直到栈中的元素为空,循环结束。

function notFirstIteration(node) {
    var stack = new Stack(),         //开辟一个新的栈对象
      resultText = &#39;&#39;;           //存放非递归遍历之后的字母顺序
    stack.push(root);            //这个root在上面非递归方式构建二叉树的时候已经构建好的
    var node = root;
    resultText += node.text;
    while(!stack.isEmpty()) {
      while(node.leftChild) {       //判断当前节点是否有左孩子节点
        node = node.leftChild;      //取当前节点的左孩子节点
        resultText += node.text;     //访问当前节点
        stack.push(node);        //将当前节点压入栈中
      }
      stack.pop();             //出栈
      node = stack.pop().rightChild;    //访问当前节点的兄弟节点(右孩子节点)
      if(node) {              //当前节点的兄弟节点不为空
        resultText += node.text;     //访问当前节点
        stack.push(node);        //将当前节点压入栈中
      }
      else {                //当前节点的兄弟节点为空
        node = stack.pop();       //在回溯到上一层
      }
    }
}
//非递归先序遍历
notFirstIteration(root);
Salin selepas log masuk

2. 中序遍历

只要把思路理清楚了现实起来其实还是挺容易的,只要我们熟悉了一种二叉树的非递归遍历方式,其他几种非递归方式就容易多了,照着葫芦画瓢,下面是中序遍历的递归方式,中序遍历的思想是:先访问左孩子节点,在访问根节点,最后访问右节点

var strText = "";
function secondIteration(node) {
    //访问左节点
    if(node.leftChild) {
      if(node.leftChild.leftChild) {
        secondIteration(node.leftChild);
      }
      else {
        strText += node.leftChild.text;
      }
    }
    //访问根节点
    strText += node.text;
    //访问右节点
    if(node.rightChild) {
      if(node.rightChild.leftChild) {
        secondIteration(node.rightChild);
      }
      else {
        strText += node.rightChild.text;
      }
    }
}
secondIteration(root);
alert(strText);
Salin selepas log masuk

中序遍历的非递归方式

思想是:1. 从根节点一直往下找左孩子节点,直到找到最后一个左孩子节点(用栈将此路径保存,但不访问)2.访问最后一个左孩子节点,然后再访问根节点(要先弹出栈,就是在栈中取上一层节点)3.在访问当前节点(最后一个左孩子节点)的兄弟节点(右孩子节点),这里要注意如果兄弟节点是一个叶节点就直接访问,否则是兄弟节点是一颗子树的话不能马上访问,要先来重复 1, 2,3步骤, 直到栈为空,循环结束

function notSecondIteration() {
    var resultText = &#39;&#39;,
      stack = new Stack(),
      node = root;
    stack.push(node);
    while(!stack.isEmpty()) {
      //从根节点一直往下找左孩子节点直到最后一个左孩子节点,然后保存在栈中
      while(node.leftChild) {
        node = node.leftChild;
        stack.push(node);
      }
      //弹出栈
      var tempNode = stack.pop();
      //访问临时节点
      resultText += tempNode.text;
      if(tempNode.rightChild) {
        node = tempNode.rightChild;
        stack.push(node);
      }
    }
    alert(resultText);
}
Salin selepas log masuk

3. 后续遍历

最后就还剩下一种遍历方式,二叉树的后续遍历,后续遍历的思想是:先访问左孩子节点,然后在访问右孩子节点,最后访问根节点

后续遍历的递归方式

var strText = &#39;&#39;;
function lastIteration(node) {
    //首先访问左孩子节点
    if(node.leftChild) {
      if(node.leftChild.leftChild) {
        lastIteration(node.leftChild);
      }
      else {
        strText += node.leftChild.text;
      }
    }
    //然后再访问右孩子节点
    if(node.rightChild) {
      if(node.rightChild.rightChild) {
        lastIteration(node.rightChild);
      }
      else {
        strText += node.rightChild.text;
      }
    }
    //最后访问根节点
    strText += node.text;
}
//中序递归遍历
lastIteration(root);
alert(strText);
Salin selepas log masuk

后续非递归遍历

后续非递归遍历的思想是:1.从根节点一直往下找左孩子节点,直到最后一个左孩子节点(将路径保存到栈中,但不访问)2.弹出栈访问最后一个左孩子节点 3.进入最后一个左孩子节点的兄弟节点,如果兄弟节点是叶节点就访问它,否则将该节点重复 1, 2步骤, 直到栈中的元素为空,循环结束。3.访问根节点

function notLastIteration() {
    var strText = &#39;&#39;,
    stack = new Stack();
    nodo = root;
    stack.push(node);
    while(!stack.isEmpty()) {
      while(node.leftChild) {
        node = node.leftChild;
        stack.push(node);
      }
      //弹出栈
      var tempNode = stack.pop();
      //访问左孩子节点
      strText += tempNode.text;
      //访问右孩子节点
      if(tempNode.rightChild) {
        if(tempNode.rightChild.leftChild || tempNode.rightChild.rightChild) { //判断最后一个左孩子节点的兄弟节点是否为页节点
          stack.push(tempNode.rightChild);
        }
        else {
          strText += tempNode.rightChild.text;
        }
      }
    }
    alert(strText);
}
Salin selepas log masuk

上面是我整理给大家的,希望今后会对大家有帮助。

相关文章:

如何使用vuex实现菜单管理

详细解读Angular5.1新功能

使用nodejs如何实现gulp打包

在vue2中通过keep-alive如何使用

在webpack中有关于jquery插件的环境配置(详细教程)

Atas ialah kandungan terperinci 使用JavaScript如何实现二叉树遍历. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

Video Face Swap

Video Face Swap

Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Artikel Panas

<🎜>: Bubble Gum Simulator Infinity - Cara Mendapatkan dan Menggunakan Kekunci Diraja
4 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
Nordhold: Sistem Fusion, dijelaskan
4 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
Mandragora: Whispers of the Witch Tree - Cara Membuka Kunci Cangkuk Bergelut
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas

Tutorial Java
1672
14
Tutorial PHP
1276
29
Tutorial C#
1256
24
Bagaimana untuk menyemak nombor siri cakera keras dan alamat mac Bagaimana untuk menyemak nombor siri cakera keras dan alamat mac Feb 18, 2024 pm 07:45 PM

Nombor siri cakera keras dan alamat MAC adalah pengecam penting dalam perkakasan komputer dan sangat berguna dalam mengurus dan menyelenggara sistem komputer. Artikel ini akan memperkenalkan cara mencari nombor siri cakera keras dan alamat MAC. 1. Cari nombor siri cakera keras Nombor siri cakera keras ialah pengecam unik yang digunakan oleh pengeluar cakera keras untuk mengenal pasti dan menjejaki cakera keras. Dalam sistem pengendalian yang berbeza, kaedah mencari nombor siri cakera keras adalah sedikit berbeza. Windows: Buka Prompt Perintah (cari "cmd" dalam menu Mula) dan masukkan arahan berikut dan tekan Enter: wmicdisk

4 Cara untuk Mematikan Cari Saya pada iPhone 4 Cara untuk Mematikan Cari Saya pada iPhone Feb 02, 2024 pm 04:15 PM

Apl Cari Saya Apple membolehkan anda mencari iPhone anda atau peranti lain untuk mengelakkannya daripada hilang atau dilupakan. Walaupun Cari Saya ialah alat yang berguna untuk menjejak peranti, anda mungkin mahu melumpuhkannya jika anda bimbang tentang isu privasi, tidak mahu menghabiskan bateri anda atau atas sebab lain. Nasib baik, terdapat beberapa cara untuk mematikan Cari Saya pada iPhone, semuanya akan kami terangkan dalam artikel ini. Cara Mematikan Cari Saya pada iPhone [4 Kaedah] Anda boleh mematikan Cari Saya pada iPhone dalam empat cara. Jika anda menggunakan Kaedah 1 untuk mematikan Cari, anda boleh melakukan ini daripada peranti yang anda mahu nyahdayakannya. Untuk meneruskan kaedah 2, 3 dan 4, iPhone yang anda ingin matikan Finder harus dimatikan atau

Apa itu Discuz? Definisi dan pengenalan fungsi Discuz Apa itu Discuz? Definisi dan pengenalan fungsi Discuz Mar 03, 2024 am 10:33 AM

"Meneroka Discuz: Definisi, Fungsi dan Contoh Kod" Dengan perkembangan pesat Internet, forum komuniti telah menjadi platform penting untuk orang ramai mendapatkan maklumat dan bertukar pendapat. Di antara banyak sistem forum komuniti, Discuz, sebagai perisian forum sumber terbuka yang terkenal di China, digemari oleh majoriti pembangun dan pentadbir laman web. Jadi, apa itu Discuz? Apakah fungsi yang ada padanya, dan bagaimana ia boleh membantu tapak web kami? Artikel ini akan memperkenalkan Discuz secara terperinci dan melampirkan contoh kod khusus untuk membantu pembaca mengetahui lebih lanjut mengenainya.

Definisi dan fungsi kunci utama komposit MySQL Definisi dan fungsi kunci utama komposit MySQL Mar 15, 2024 pm 05:18 PM

Kunci utama komposit dalam MySQL merujuk kepada kunci utama yang terdiri daripada pelbagai medan dalam jadual, yang digunakan untuk mengenal pasti setiap rekod secara unik. Tidak seperti kunci utama tunggal, kunci utama komposit dibentuk dengan menggabungkan nilai berbilang medan. Apabila membuat jadual, anda boleh menentukan kunci utama komposit dengan menentukan berbilang medan sebagai kunci utama. Untuk menunjukkan definisi dan fungsi kunci utama komposit, kami mula-mula membuat jadual bernama pengguna, yang mengandungi tiga medan: id, nama pengguna dan e-mel, dengan id ialah kunci utama dan pengguna yang meningkat secara automatik

Java bagaimana untuk menggelung melalui folder dan mendapatkan semua nama fail Java bagaimana untuk menggelung melalui folder dan mendapatkan semua nama fail Mar 29, 2024 pm 01:24 PM

Java ialah bahasa pengaturcaraan yang popular dengan keupayaan pengendalian fail yang berkuasa. Di Java, melintasi folder dan mendapatkan semua nama fail adalah operasi biasa, yang boleh membantu kami mencari dan memproses fail dengan cepat dalam direktori tertentu. Artikel ini akan memperkenalkan cara melaksanakan kaedah melintasi folder dan mendapatkan semua nama fail dalam Java, dan memberikan contoh kod khusus. 1. Gunakan kaedah rekursif untuk melintasi folder Kita boleh menggunakan kaedah rekursif untuk melintasi folder.

Bagaimana untuk mencari nombor siri pemacu keras komputer anda Bagaimana untuk mencari nombor siri pemacu keras komputer anda Feb 20, 2024 am 10:33 AM

Cara Menyemak Nombor Siri Pemacu Keras Komputer Dengan perkembangan teknologi komputer, pemacu keras komputer telah menjadi bahagian yang amat diperlukan dalam kehidupan kita. Sama ada ia menyimpan fail penting atau memasang sistem pengendalian dan perisian, anda perlu bergantung pada cakera keras untuk menyelesaikannya. Memahami beberapa maklumat asas tentang pemacu keras komputer, seperti nombor siri pemacu keras, boleh membantu kami mengurus dan menyelenggara sistem komputer dengan lebih baik. Jadi, bagaimana untuk menyemak nombor siri cakera keras komputer? Artikel ini akan memperkenalkan beberapa kaedah biasa. Kaedah 1: Gunakan alat baris arahan yang disertakan dengan sistem Windows sistem Windows

Tutorial JavaScript Mudah: Cara Mendapatkan Kod Status HTTP Tutorial JavaScript Mudah: Cara Mendapatkan Kod Status HTTP Jan 05, 2024 pm 06:08 PM

Tutorial JavaScript: Bagaimana untuk mendapatkan kod status HTTP, contoh kod khusus diperlukan: Dalam pembangunan web, interaksi data dengan pelayan sering terlibat. Apabila berkomunikasi dengan pelayan, kami selalunya perlu mendapatkan kod status HTTP yang dikembalikan untuk menentukan sama ada operasi itu berjaya dan melaksanakan pemprosesan yang sepadan berdasarkan kod status yang berbeza. Artikel ini akan mengajar anda cara menggunakan JavaScript untuk mendapatkan kod status HTTP dan menyediakan beberapa contoh kod praktikal. Menggunakan XMLHttpRequest

Pengenalan kepada antara muka PHP dan cara mentakrifkannya Pengenalan kepada antara muka PHP dan cara mentakrifkannya Mar 23, 2024 am 09:00 AM

Pengenalan kepada antara muka PHP dan bagaimana ia ditakrifkan PHP ialah bahasa skrip sumber terbuka yang digunakan secara meluas dalam pembangunan Web Ia fleksibel, mudah dan berkuasa. Dalam PHP, antara muka ialah alat yang mentakrifkan kaedah biasa antara pelbagai kelas, mencapai polimorfisme dan menjadikan kod lebih fleksibel dan boleh digunakan semula. Artikel ini akan memperkenalkan konsep antara muka PHP dan cara mentakrifkannya, dan menyediakan contoh kod khusus untuk menunjukkan penggunaannya. 1. Konsep antara muka PHP Antara muka memainkan peranan penting dalam pengaturcaraan berorientasikan objek, mentakrifkan aplikasi kelas

See all articles