数据结构之双向链表、二叉树

 

数据结构之双向链表、二叉树

/**

 *

 *双向链表实现

 *

 */

public class MyLinkedList {

  private Node first;//链表的第一个节点

  private Node last;//链表的最后一个节点

  private int size;//节点的数量

       

 //使用到内部类  描述节点

class Node{

Node prev;//上一个节点对象

Node next;//下一个节点对象

Object ele; // 当前节点中存储的值

//提供一个构造用来初始化节点值

public Node(Object ele) {

this.ele = ele;

}

}

/**

 * 添加节点 前

 * @param ele 节点中的值

 */

public void addFirst(Object ele) {

 //1.创建节点对象

Node node = new Node(ele);

//2.判断是否是第一次插入节点

if(size == 0) { //第一次插入节点

this.first = node;//设置为头节点

this.last = node;//设置为尾节点

}else {//若执行else说明节点已经存在,需要将节点进行串联

//进行节点连接,当前节点即node应该在原有节点的前面

node.next = this.first;

//原有来节点需要连接当前节点即node

this.first.prev = node;

//更新节点将头节点赋值给node

this.first = node;

}

size++;//节点数+1

}

/**

 * 添加节点 后

 * @param ele 元素值

 */

public void addLast(Object ele) {

//1.先创建节点对象

Node node = new Node(ele);

//需要判断是不是第一次添加节点

if(size == 0) {

this.first = node;//添加头节点

this.last =  node;//添加尾节点

}else {//当前已经不是第一次插入节点,需要串联节点

//原节点的下一位是当前节点即node

this.last.next = node;

//当前节点即node的上一位是原有节点

node.prev = this.last;

//将原有的尾部设置给当前节点即node

this.last = node;

 

}

//节点数自增

size ++;

}

 

/**

 *节点删除

 */

 public void remove(Object ele) {

 //知道被删除的节点

 Node current = this.first;//获取头节点进行遍历

 for(int i = 0; i<size;i++) {

 if(!current.ele.equals(ele)) {//current.ele.equals(ele)不相等--> false  !false --> true

 if(current.next == null) { //判断是否还有下一个节点,return 结束

 return;

 }

 current = current.next; //下一个节点

 }

 

 }

 //删除具体节点

 if(current == first) {//头

 this.first = current.next;

 this.first.prev = null;

 }else if(current == last) {//尾

 this.last = current.prev;

 this.last.next = null;

 }else {//某个位置

 //把删除节点的上一个节点的下一位置连接到删除节点的下一个节点

 current.prev.next = current.next;

 //把删除节点的下一个节点的上个位置连接到删除节点的上一个节点

 current.next.prev = current.prev;

 }

 //大小需要-1操作

 size--;

 }

 

@Override

public String toString() {

if(size == 0) {

return "[]";

}

StringBuilder bs = new StringBuilder();

//第一个节点

Node current = this.first;

bs.append("[");

for(int i = 0 ;i<size;i++) {

bs.append(current.ele);//取值

if(i != size-1) {

bs.append(",");

}else {

bs.append("]");

}

current = current.next;//获取下一个节点

}

return bs.toString();

}

 

}

 

 

 

二叉树的Java实现及特点总结

二叉树是一种非常重要的数据结构,它同时具有数组和链表各自的特点:它可以像数组一样快速查找,也可以像链表一样快速添加。但是他也有自己的缺点:删除操作复杂。

我们先介绍一些关于二叉树的概念名词。

二叉树:是每个结点最多有两个子树的有序树,在使用二叉树的时候,数据并不是随便插入到节点中的,_x001D_一个节点的左子节点的关键值必须小于此节点,右子节点的关键值必须大于或者是等于此节点,所以又称二叉查找树、二叉排序树、二叉搜索树。

完全二叉树:若设二叉树的高度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第h层有叶子结点,并且叶子结点都是从左到右依次排布,这就是完全二叉树。

满二叉树——除了叶结点外每一个结点都有左右子叶且叶子结点都处在最底层的二叉树。

深度——二叉树的层数,就是深度。

二叉树的特点总结:

   大O算法 --> 中型以上

(1)树执行查找、删除、插入的时间复杂度都是O(logN)

(2)遍历二叉树的方法包括前序、中序、后序

(3)非平衡树指的是根的左右两边的子节点的数量不一致

(4) 在非叉树空二中,第i层的结点总数不超过 , i>=1;

(5)深度为h的二叉树最多有个结点(h>=1),最少有h个结点(平衡)

(6)对于任意一棵二叉树,如果其叶结点数为N0,而度数为2的结点总数为N2,则N0=N2+1;

二叉树遍历分为三种

先序遍历

首先访问根,再先序遍历左子树,最后先序遍历右子树

中序遍历

首先中序遍历左子树,再访问根,最后中序遍历右子树

后序遍历

首先后序遍历左子树,再后序遍历右子树,最后访问根

 

二叉树的Java代码实现

首先是树的节点的定义,下面的代码中使用的是最简单的int基本数据类型作为节点的数据,如果要使用节点带有更加复杂的数据类型,换成对应的对象即可。

/**

 * 树节点

 *

 * @author JKMaster

 *

 */

伪代码...

class TreeNode{

TreeNode leftTreeNode;

 ....     rightTreeNode;

 Int value;

   .....    //状态

  //get  和  set  方法 用于变量

 // 构造

 

}

 

 

public class TreeNode {

    // 左节点

private TreeNode lefTreeNode;

// 右节点

private TreeNode rightNode;

// 数据

private int value;

 

private boolean isDelete;//节点状态

 

public TreeNode getLefTreeNode() {

return lefTreeNode;

}

 

public void setLefTreeNode(TreeNode lefTreeNode) {

this.lefTreeNode = lefTreeNode;

}

 

public TreeNode getRightNode() {

return rightNode;

}

 

public void setRightNode(TreeNode rightNode) {

this.rightNode = rightNode;

}

 

public int getValue() {

return value;

}

 

public void setValue(int value) {

this.value = value;

}

 

public boolean isDelete() {

return isDelete;

}

 

public void setDelete(boolean isDelete) {

this.isDelete = isDelete;

}

 

public TreeNode() {

super();

}

 

public TreeNode(int value) {

this(null, null, value, false);

}

 

public TreeNode(TreeNode lefTreeNode, TreeNode rightNode, int value, boolean isDelete) {

super();

this.lefTreeNode = lefTreeNode;

this.rightNode = rightNode;

this.value = value;

this.isDelete = isDelete;

}

 

@Override

public String toString() {

return "TreeNode [lefTreeNode=" + lefTreeNode + ", rightNode=" + rightNode + ", value=" + value + ", isDelete="

+ isDelete + "]";

}

}

 

 

 

/**

 * 二叉树定义

 *

 * @author JKMaster

 *

 */

public class BinaryTree {

// 根节点

private TreeNode root;

 

public TreeNode getRoot() {

return root;

}

 

/**

 * 插入操作

 *

 * @param value

 */

public void insert(int value) {

 

TreeNode newNode = new TreeNode(value);

 

if (root == null) {

root = newNode;

root.setLefTreeNode(null);

root.setRightNode(null);

} else {

 

TreeNode currentNode = root;

TreeNode parentNode;

 

while (true) {

 

parentNode = currentNode;

// 往右放

if (newNode.getValue() > currentNode.getValue()) {

currentNode = currentNode.getRightNode();

if (currentNode == null) {

parentNode.setRightNode(newNode);

return;

}

} else {

// 往左放

currentNode = currentNode.getLefTreeNode();

if (currentNode == null) {

parentNode.setLefTreeNode(newNode);

return;

}

 

}

}

}

}

 

/**

 * 查找

 *

 * @param key

 * @return

 */

public TreeNode find(int key) {

 

TreeNode currentNode = root;

 

if (currentNode != null) {

 

while (currentNode.getValue() != key) {

 

if (currentNode.getValue() > key) {

currentNode = currentNode.getLefTreeNode();

} else {

currentNode = currentNode.getRightNode();

}

 

if (currentNode == null) {

return null;

}

 

}

 

if (currentNode.isDelete()) {

return null;

} else {

return currentNode;

}

 

} else {

return null;

}

 

}

 

/**

 * 中序遍历 (主要的)

 *

 * @param treeNode

 */

public void inOrder(TreeNode treeNode) {

if (treeNode != null && treeNode.isDelete() == false) {

inOrder(treeNode.getLefTreeNode());

System.out.println("--" + treeNode.getValue());

inOrder(treeNode.getRightNode());

}

}

 

/**

     * 先序遍历 (次要)

     *  

     * 这三种不同的遍历结构都是一样的,只是先后顺序不一样而已

     *  

     * @param node

     *            遍历的节点

     */  

 

  public static void preOrderTraverse(TreeNode treeNode) {

     if (treeNode != null ) {

    System.out.println("--" + treeNode.getValue());

    preOrderTraverse(treeNode.getLefTreeNode());

        preOrderTraverse(treeNode.getRightNode());

     }

 }

  

  

    /**

     * 后序遍历 (次要)

     *  

     * 这三种不同的遍历结构都是一样的,只是先后顺序不一样而已

     *  

     * @param node

     *            遍历的节点

     */  

 

    public static void postOrderTraverse(TreeNode treeNode) {

       if (treeNode != null ) {

       postOrderTraverse(treeNode.getRightNode());

          System.out.println("--" + treeNode.getValue());

       postOrderTraverse(treeNode.getLefTreeNode());

    

    

       }

   }

}

 

 

 

/**

 * 测试

 * @author JKMaster

 *

 */

public class TestBinaryTree {

      public static void main(String[] args) {

       BinaryTree tree = new BinaryTree();

       // 添加数据测试

       tree.insert(10);

       tree.insert(40);

       tree.insert(20);

       tree.insert(3);

       tree.insert(49);

       tree.insert(13);

       tree.insert(123);

 

       System.out.println("root=" + tree.getRoot().getValue());

       // 排序测试

       tree.inOrder(tree.getRoot());

       // 查找测试

       if (tree.find(10) != null) {

        System.out.println("找到了");

       } else {

        System.out.println("没找到");

       }

       // 删除测试

       tree.find(40).setDelete(true);

 

       if (tree.find(40) != null) {

        System.out.println("找到了");

       } else {

        System.out.println("没找到");

       }

 

      }

}

 

 

相关文章:

  • 2021-07-06
  • 2021-05-18
  • 2021-09-11
  • 2022-12-23
  • 2022-12-23
  • 2021-07-07
  • 2021-07-07
猜你喜欢
  • 2022-12-23
  • 2021-09-03
  • 2021-08-11
  • 2022-12-23
  • 2021-10-13
  • 2022-12-23
  • 2021-09-09
相关资源
相似解决方案