IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 数据结构与算法——哈希表,二叉树,堆,赫夫曼树 -> 正文阅读

[数据结构与算法]数据结构与算法——哈希表,二叉树,堆,赫夫曼树

哈希表

google公司的一个上机题

思路分析:

Emp 表示一个个雇员节点,里面有id name next属性

EmpLinkedList 表示链表 里面有head 直接表示第一个Emp,根据第一个Emp.next 接下去

HashTab 里面有一个数组,可以装入EmpLinkedList元素

package com.tt12.hashtab;

import java.util.Scanner;

public class HashTabDemo {
    public static void main(String[] args) {
        //测试添加和遍历功能
        HashTab hashTab = new HashTab(7);
        //简单菜单
        String key = "";
        Scanner scanner = new Scanner(System.in);
        while (true) {
            System.out.println("add : 添加雇员");
            System.out.println("list : 显示雇员");
            System.out.println("exit : 退出程序");

            key = scanner.next();
            switch (key) {
                case "add" :
                    System.out.println("输入id");
                    int id = scanner.nextInt();
                    System.out.println("输入名字");
                    String name = scanner.next();
                    Emp emp = new Emp(id,name);
                    hashTab.add(emp);
                    break;
                case "list" :
                    hashTab.list();
                    break;
                case "exit" :
                    scanner.close();
                    System.exit(0);
                default:
                    break;
            }
        }
    }
}

//哈希表 管理多条链表
class HashTab {
    public EmpLinkedList[] empLinkedListArray; //数组里面放的链表
    public int size; //表示共有多少条链表
    //构造器
    public HashTab(int size) {
        this.size = size;
        //初始化链表数组
        empLinkedListArray = new EmpLinkedList[size];
        //数组里面的元素是null 还需要初始化链表开辟内存
        for(int i = 0; i < size; i++) {
            empLinkedListArray[i] = new EmpLinkedList();
        }
    }

    //添加
    public void add(Emp emp) {
        //根据员工的id得到该员工应该添加到哪条链表
        int empLinkedListNo = hashFun(emp.id);
        //添加到对应链表
        empLinkedListArray[empLinkedListNo].add(emp);
    }

    //编写散列函数,使用一个简答的取模法
    public int hashFun(int id) {
        return id % size;
    }

    //遍历所有的链表
    public void list() {
        for(int i = 0; i < size; i++) {
            empLinkedListArray[i].list(i);
        }
    }
}
//表示一个雇员
class Emp {
    public int id;
    public String name;
    public Emp next;
    //构造器
    public Emp(int id, String name) {
        super();
        this.id = id;
        this.name = name;
    }
}

//创建 EmpLinkedList 表示链表
class EmpLinkedList {
    //这个链表的head直接指向第一个Emp,没有所谓的头指针
    public Emp head;

    //添加
    //说明: 假定添加雇员时,id自增长
    public void add(Emp emp) {
        if (head == null) {
            head = emp;
            return;
        }

        Emp curEmp = head; //辅助指针
        while (true) {
            if (curEmp.next == null) {
                break;
            }
            curEmp = curEmp.next;
        }
        //退出while时curEmp指向最后一个节点 这是将要加的emp接上
        curEmp.next = emp;
    }

    //遍历
    public void list(int no) {
        if (head == null) {
            System.out.println("第" + no + "条链表为空");
            return;
        }
        System.out.print("第" + no + "条链表信息为 ");
        Emp curEmp = head;
        while (true) {
            System.out.printf("=> id=%d name=%s\t", curEmp.id, curEmp.name);
            if (curEmp.next == null) {
                break;
            }
            curEmp = curEmp.next;
        }
        System.out.println();
    }
}

二叉树

为什么需要树这种数据结构

树的常用术语

二叉树的概念

二叉树遍历的说明

1)前序遍历

先输出当前节点(初始时是root节点)

如果左子节点不为null,则递归继续前序遍历

如果右子节点不为null,则递归继续前序遍历

2)中序遍历

如果当前节点的左子节点不为null,则递归中序遍历

输出当前节点

如果当前节点的右子节点不为null,则递归中序遍历

3)后序遍历

如果当前节点的左节点不为空,则递归后序遍历

如果当前节点的右子节点不为null,则递归中序遍历

输出当前节点

使用前中后序分别遍历下面的二叉树

package com.tt12.tree;

public class BinaryTreeDemo {
    public static void main(String[] args) {
        //创建二叉树
        BinaryTree binaryTree = new BinaryTree();
        //创建需要的节点
        HeroNode root = new HeroNode(1, "宋江");
        HeroNode node2 = new HeroNode(2, "吴用");
        HeroNode node3 = new HeroNode(3, "卢俊义");
        HeroNode node4 = new HeroNode(4, "林冲");
        //手动创建该二叉树,后面学习递归创建二叉树
        root.left = node2;
        root.right = node3;
        node3.right = node4;
        binaryTree.root = root;

        //测试遍历
        System.out.println("前序遍历");
        binaryTree.preOrder();
        System.out.println("中序遍历");
        binaryTree.infixOrder();
        System.out.println("后序遍历");
        binaryTree.postOrder();
    }
}

//定义二叉树
class BinaryTree {
    public HeroNode root;
    //前序遍历
    public void preOrder() {
        if(this.root != null) {
            this.root.preOrder();
        }else {
            System.out.println("二叉树为空无法遍历");
        }
    }
    //中序遍历
    public void infixOrder() {
        if(this.root != null) {
            this.root.infixOrder();
        }else {
            System.out.println("二叉树为空无法遍历");
        }
    }
    //后序
    public void postOrder() {
        if(this.root != null) {
            this.root.postOrder();
        }else {
            System.out.println("二叉树为空无法遍历");
        }
    }
}

//先创建HeroNode节点
class HeroNode {
    public int no;
    public String name;
    public HeroNode left;
    public HeroNode right;
    //构造器
    public HeroNode(int no, String name) {
        this.no = no;
        this.name = name;
    }
    @Override
    public String toString() {
        return "HeroNode [no = " + no + ", name = " + name +  "]";
    }
    //前序遍历的方法
    public void preOrder() {
        System.out.println(this);
        if(this.left != null) {
            this.left.preOrder();
        }
        if(this.right != null) {
            this.right.preOrder();
        }
    }
    //中序
    public void infixOrder(){
        if(this.left != null) {
            this.left.infixOrder();
        }
        System.out.println(this);
        if(this.right != null) {
            this.right.infixOrder();
        }
    }
    //后序
    public void postOrder() {
        if(this.left != null) {
            this.left.postOrder();
        }
        if(this.right != null) {
            this.right.postOrder();
        }
        System.out.println(this);
    }

}

二叉树的前中后序查找

class HeroNode {
    public int no;
    public String name;
    public HeroNode left;
    public HeroNode right;
    //构造器
    public HeroNode(int no, String name) {
        this.no = no;
        this.name = name;

    //前序查找
    public HeroNode preOrderSearch(int no) {
        if(no == this.no) {
            return this;
        }
        HeroNode resNode = null;
        if(this.left != null) {
            resNode  = this.left.preOrderSearch(no);
        }
        if(resNode != null) {
            return resNode;
        }
        if(this.right != null) {
            resNode = this.right.preOrderSearch(no);
        }
        return resNode;
    }
    //中序查找
    public HeroNode infixOrderSearch(int no) {
        HeroNode resNode = null;
        if(this.left != null) {
            resNode = this.left.infixOrderSearch(no);
        }
        if(resNode != null) {
            return resNode;
        }
        if(this.no == no) {
            return this;
        }
        if(this.right != null) {
            resNode = this.right.infixOrderSearch(no);
        }
        return resNode;
    }
    //后序查找
    public HeroNode postOrderSearch(int no) {
        HeroNode resNode= null;
        if(this.left != null) {
            resNode = this.left.postOrderSearch(no);
        }
        if(resNode != null) {
            return resNode;
        }
        if(this.right != null) {
            resNode = this.right.postOrderSearch(no);
        }
        return resNode;
    }    
 }

二叉树的删除节点

class BinaryTree {
    public HeroNode root;

    //删除
    public void delNode(int no) {
        if(root != null){
            if(root.no == no) {
                root = null;
            }else {
                root.delNode(no);
            }
        }else {
            System.out.println("空树");
        }
    }
}

class HeroNode {
    public int no;
    public String name;
    public HeroNode left;
    public HeroNode right;
    //构造器
    public HeroNode(int no, String name) {
        this.no = no;
        this.name = name;
    }
    @Override
    public String toString() {
        return "HeroNode [no = " + no + ", name = " + name +  "]";
    }

    /*
    删除节点
    规定:如果删除的节点是叶子节点,则删除该节点
         如果删除的节点是非叶子节点,则删除该子树
    */
    public void delNode(int no) {
        if(this.left != null && this.left.no == no) {
            this.left = null;
            return;
        }
        if(this.right != null && this.right.no == no) {
            this.right = null;
            return;
        }
        if(this.left != null) {
            this.left.delNode(no);
        }
        if(this.right != null) {
            this.right.delNode(no);
        }
    }
}

顺序存储二叉树

顺序存储二叉树的概念?

顺序存储二叉树的特点

线索化二叉树

线索化二叉树基本介绍

?线索化二叉树应用案例以及遍历

package com.tt12.tree;

public class ThreadedBinaryTreeDemo {
    public static void main(String[] args) {
        ThreadedHeroNode root = new ThreadedHeroNode(1,"tom");
        ThreadedHeroNode node2 = new ThreadedHeroNode(3,"jack");
        ThreadedHeroNode node3 = new ThreadedHeroNode(6,"smith");
        ThreadedHeroNode node4 = new ThreadedHeroNode(8,"mary");
        ThreadedHeroNode node5 = new ThreadedHeroNode(10,"tom");
        ThreadedHeroNode node6 = new ThreadedHeroNode(14,"dim");

        root.left = node2;
        root.right = node3;
        node2.left = node4;
        node2.right = node5;
        node3.left = node6;

        ThreadedBinaryTree threadedBinaryTree = new ThreadedBinaryTree();
        threadedBinaryTree.root = root;
        threadedBinaryTree.infixOrderThreaded(root);

        ThreadedHeroNode testNode = node5;
        System.out.println(node5.left.toString());

        threadedBinaryTree.infixOrderThreadedList();
    }
}

//线索化二叉树
class ThreadedBinaryTree extends BinaryTree {
    //编写对二叉树进行 【中序线索化】 的方法
    //为了实现线索化,需要一个指针,指向要线索化节点的前一节点
    public ThreadedHeroNode pre = null;
    public void infixOrderThreaded(ThreadedHeroNode node) {
        if(node == null) {
            return;
        }
        //先线索化 左子树
        infixOrderThreaded((ThreadedHeroNode) node.left);
        //处理当前节点的前驱节点
        if(node.left == null) {
            node.left = pre;
            node.leftType = true;
        }
        //处理后继节点
        if(pre != null && pre.right == null) {
            pre.right = node;
            pre.rightType = true;
        }
        //每处理一个节点后,让当前节点是下一个节点的前驱节点
        pre = node;
        //右子树
        infixOrderThreaded((ThreadedHeroNode) node.right);
    }

    //中序遍历线索化二叉树的方法
    public void infixOrderThreadedList() {
        ThreadedHeroNode node = (ThreadedHeroNode) root;
        while(node != null) {
            while(node.leftType == false) {
                node = (ThreadedHeroNode) node.left;
            }

            System.out.println(node.toString());
            while(node.rightType == true) {
                node = (ThreadedHeroNode) node.right;
                System.out.println(node);
            }
            node = (ThreadedHeroNode) node.right;
        }
    }
}


class ThreadedHeroNode extends HeroNode {
    //说明:
    //如果leftType == 0(false) 表示指向左子树 如果== 1(true)表示指向前驱节点
    //如果rightType == 0 表示指向右子树,== 1 表示指向后继节点
    public boolean leftType;
    public boolean rightType;

    public ThreadedHeroNode(int no, String name) {
        super(no, name);
    }
}

赫夫曼树

基本介绍

?

?构建赫夫曼树思路

package com.tt12.huffmantree;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Huffmantree {
    public static void main(String[] args) {
        int arr[] = {13, 7, 8, 3, 29, 6, 1};
        //测试赫夫曼树已经建成
    }

    //创建赫夫曼树的方法
    public static Node createHuffmanTree(int arr[]) {
        //遍历arr数组,将每个元素构建成一个Node,将这个Node放入ArrayList中
        List<Node> nodes = new ArrayList<Node>();
        for(int value : arr) {
            nodes.add(new Node(value));
        }
        
        while (nodes.size() > 1) {
            //排序 从小到大
            Collections.sort(nodes);
            //取出根节点权值最小的两颗二叉树(一个节点也可以看作一颗二叉树)
            Node leftNode = nodes.get(0);
            Node rightNode = nodes.get(1);
            Node parent = new Node(leftNode.value + rightNode.value);
            parent.left = leftNode;
            parent.right = rightNode;

            //从List中删除已经处理过的Node
            nodes.remove(leftNode);
            nodes.remove(rightNode);
            //将parent加入List
            nodes.add(parent);
            //重新排序
            Collections.sort(nodes);
        }
        return nodes.get(0);
    }
}

//创建节点类
//为了让Node对象支持排序 让Node实现Comparable<Node>接口
class Node implements Comparable<Node> {
    int value; //节点权值
    Node left; //指向左子节点
    Node right; //指向右子节点
    
    public Node(int value) {
        this.value = value;
    }
    public String toString() {
        return "Node [value = " + value + "]";
    }
    public int compareTo(Node o) {
        //表示从小到大排序
        return this.value - o.value;
    }
}

赫夫曼编码

基本介绍

通讯领域中信息的处理方式1——定长编码

通讯领域中信息的处理方式2——变长编码

?赫夫曼编码的原理剖析

?创建赫夫曼树

?

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-08-19 19:31:09  更:2022-08-19 19:32:18 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/28 18:26:04-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计