查找算法、哈希表、树
       

开始~~~


目录

  • 一、查找算法
    • 1.线性查找
    • 2.二分查找
      • 2.1思路分析
      • 2.2代码
    • 3.插值查找
      • 3.1插值查找原理的介绍
      • 3.2代码
    • 4.斐波那契查找
    • 5.哈希表
      • 5.1哈希表的基本介绍
      • 5.2图解
      • 5.3代码
  • 二、二叉树
    • 1.二叉树介绍
      • 1.1为什么需要树这种数据结构
      • 1.2树的示意图
      • 1.3二叉树的概念
    • 2.二叉树遍历
      • 2.1遍历的说明
      • 2.2代码
    • 3.二叉树查找
      • 3.1代码
    • 4.二叉树的删除
      • 4.1思路分析
      • 4.2代码
    • 5.顺序存储二叉树
      • 5.1说明
      • 5.2特点
      • 5.3代码
    • 6.线索化二叉树
      • 6.1问题分析
      • 6.2基本介绍
      • 6.3思路分析
      • 6.4代码
  • 总结

一、查找算法

1.线性查找

简单直接代码,从第一个数组开始找。

public void orderSearch(int value) {for (int i = 0; i < arr.length; i++) {if (arr[i] != value) {} else {System.out.println("索引为:" + i);return;}}System.out.println("没有找到数据~~");
}

2.二分查找

2.1思路分析

前提是数组是升序排列的,这里考虑到数组中可能有多个重复值。
       主要是通过递归:
       1)获得数组arr中间值的索引mid = (left + right) / 2,并与查找值findValue做比较。
       2)如果arr[mid] = findValue,则结束循环,并且比较mid左右两端的数据看是否等于findValue
       3)如果arr[mid] < findValue,需要向右递归。将mid + 1作为left
       4)如果arr[mid] > findValue,需要向左递归。将mid - 1作为right
       5)否则没有找到

2.2代码

public void binarySearch(int value, int left, int right) {int mid = (left + right) / 2;if (arr[mid] == value) {ArrayList list = new ArrayList();list.add(mid);int temp = mid + 1;while (temp < arr.length) {if (arr[temp] == value) {list.add(temp);}temp += 1;}temp = mid - 1;while (temp >= 0) {if (arr[temp] == value) {list.add(temp);}temp -= 1;}System.out.println("索引为:");list.forEach(System.out::println);} else if (arr[mid] < value) {binarySearch(value, mid + 1, right);} else if (arr[mid] > value) {binarySearch(value, left, mid - 1);} else {System.out.println("没有找到~~~");}
}

3.插值查找

3.1插值查找原理的介绍

插值查找算法类似于二分查找,不同的是插值查找每次从自适应mid处开始查找。
       公式:
mid = left + (right – left) * (findVal – arr[left]) / (arr[right] – arr[left])

3.2代码

public void insertValSearch(int value, int low, int high) {int mid = low + (high - low) * (value - arr[low]) / (arr[high] - arr[low]);if (value > arr[arr.length - 1] || value < arr[0]){System.out.println("没有找到~~");}else{if (arr[mid] == value){System.out.println("索引为:" + mid);}else if (value > arr[mid]){insertValSearch(value,mid + 1,high);}else if (value < arr[mid]){insertValSearch(value,low,mid - 1);}else{System.out.println("没有找到~~");}}
}

4.斐波那契查找

~~

5.哈希表

一个实际的需求:
       有一个公司,当有新的员工来报道时,要求将该员工的信息加入(id,性别,年龄,住址…),当输入该员工的id时,要求查找到该员工的 所有信息.
       要求: 不使用数据库,尽量节省内存,速度越快越好=>哈希表(散列)

5.1哈希表的基本介绍

散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。

5.2图解

5.3代码

1)添加成员、查找成员、遍历成员信息

class HashTable{private int size;private Manage[] manage;public HashTable(int size){this.size = size;this.manage = new Manage[size];for (int i = 0; i < size; i++) {manage[i] = new Manage();}}//添加public void add(Employees emp){int index = emp.getId() % size;manage[index].add(emp);}//遍历public void show(){for (int i = 0; i < size; i++) {System.out.println("第" + (i + 1) + "条链表:");manage[i].show();}}//查找public void find(int id){int index = id % size;Employees emp = manage[index].find(id);if (emp == null){System.out.println("没有查到该员工信息");}else{System.out.println("查询的员工信息在第" + (index + 1) + "条链表中:");System.out.println(emp);}}
}
//创建员工信息类
class Employees{private int id;private String name;private int age;public Employees next;public Employees(int id, String name, int age) {this.id = id;this.name = name;this.age = age;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "employees{" +"id=" + id +", name=" + name +", age=" + age +'}';}
}
//管理员工信息
class Manage{private Employees head;//添加成员信息public void add(Employees emp){if(head == null){head = emp;}else{head.next = emp;}System.out.println("添加成功");}//显示成员信息public void show(){Employees temp = head;if (head == null){System.out.println("无员工信息");}else{while (temp != null){System.out.println(temp);temp = temp.next;}}}//查找成员信息public Employees find(int num){Employees temp = head;if (head == null){return null;}else{while (temp != null){if (temp.getId() == num){return  temp;}temp = temp.next;}return null;}}
}

2)操作界面

HashTable list = new HashTable(7);
boolean loop = true;
Scanner scan = new Scanner(System.in);
char key;
while (loop){System.out.println("-----------雇员操作界面-----------");System.out.println("        a(add):添加雇员数据");System.out.println("       s(show):显示雇员信息");System.out.println("       f(find):查找雇员信息");System.out.println("         e(exit):退出程序");System.out.print("请输入操作类型:");key = scan.next().charAt(0);switch (key){case 'a':System.out.println("-----------添加员工信息-----------");System.out.print("请输入员工编号:");int id = scan.nextInt();System.out.print("请输入员工姓名:");String name = scan.next();System.out.print("请输入员工年龄:");int age = scan.nextInt();Employees emp = new Employees(id, name, age);list.add(emp);break;case 's':System.out.println("-----------显示员工信息-----------");list.show();break;case 'f':System.out.println("-----------查找员工信息-----------");System.out.print("输入要查找的员工id:");int no = scan.nextInt();list.find(no);break;case 'e':loop = false;System.out.println("退出成功~~~");break;}
}

二、二叉树

1.二叉树介绍

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

简单的说: 递归就是方法自己调用自己,每次调用时传入不同的变量.递归有助于编程者解决复杂的问题,同时可以让代码变得简洁。
       1)数组存储方式的分析
       优点:通过下标方式访问元素,速度快。对于有序数组,还可使用二分查找提高检索速度。
       缺点:如果要检索具体某个值,或者插入值(按一定顺序)会整体移动,效率较低。
       2)链式存储方式的分析
       优点:在一定程度上对数组存储方式有优化(比如:插入一个数值节点,只需要将插入节点,链接到链表中即可, 删除效率也很好)。
       缺点:在进行检索时,效率仍然较低,比如(检索某个值,需要从头节点开始遍历) 。
       3)树存储方式的分析
       能提高数据存储,读取的效率, 比如利用 二叉排序树(Binary Sort Tree),既可以保证数据的检索速度,同时也可以保证数据的插入,删除,修改的速度。

1.2树的示意图

1.3二叉树的概念

1)树有很多种,每个节点最多只能有两个子节点的一种形式称为二叉树。
       2)二叉树的子节点分为左节点和右节点。

       3)如果该二叉树的所有叶子节点都在最后一层,并且结点总数= 2^n -1 , n 为层数,则我们称为满二叉树。
       4)如果该二叉树的所有叶子节点都在最后一层或者倒数第二层,而且最后一层的叶子节点在左边连续,倒数第二层的叶子节点在右边连续,我们称为完全二叉树。


2.二叉树遍历

2.1遍历的说明

前序遍历: 先输出父节点,再遍历左子树和右子树
       中序遍历: 先遍历左子树,再输出父节点,再遍历右子树
       后序遍历: 先遍历左子树,再遍历右子树,最后输出父节点
       小结: 看输出父节点的顺序,就确定是前序,中序还是后序

2.2代码

1)前序遍历

public void preOrder(){System.out.println(this);if (this.left != null) {this.left.preOrder();}if (this.right != null) {this.right.preOrder();}
}

2)中序遍历

public void midOrder(){if (this.left != null) {this.left.midOrder();}System.out.println(this);if (this.right != null) {this.right.midOrder();}
}

3)后序遍历

public void lasOrder(){if (this.left != null) {this.left.lasOrder();}if (this.right != null) {this.right.lasOrder();}System.out.println(this);
}

3.二叉树查找

同样也是分为前序遍历查找,中序遍历查找,后序遍历查找。

3.1代码

1)前序遍历查找

public HeroNode preSearch(int no){if (this.no == no){return this;}HeroNode node = null;if (this.left != null){node = this.left.preSearch(no);}if (node != null){return node;}if (this.right != null){node = this.right.preSearch(no);}return node;
}

2)中序遍历查找

public HeroNode midSearch(int no){HeroNode node = null;if (this.left != null){node = this.left.midSearch(no);}if (this.no == no){return this;}if (node != null){return node;}if (this.right != null){node = this.right.midSearch(no);}return node;
}

3)后序遍历查找

public HeroNode postSearch(int no){HeroNode node = null;if (this.left != null){node = this.left.postSearch(no);}if (node != null){return node;}if (this.right != null){node = this.right.postSearch(no);}if (node != null){return node;}if (this.no == no){return this;}return node;
}

4.二叉树的删除

4.1思路分析

规定:
       1)如果删除的是叶子结点,则删除该叶子结点。
       2)如果删除的是非叶子结点,则删除该子树。
       3)如果要删除的节点是root节点,则将整个二叉树置空即可。
       4)需要通过this.leftthis.right找到需要删除的节点位置。
       步骤:
       1)如果this.left.no = findNo
this.right.no = findNo,则找到了要删除的节点。
       2)否则依次进行左递归和右递归,遍历整个子树找到对应的no值,删除节点。

4.2代码

public void delete(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.delete(no);}if (this.right != null){this.right.delete(no);}
}

5.顺序存储二叉树

5.1说明

数组存储方式和树的存储方式可以相互转换,即数组可以转换成树,树也可以转换成数组。

5.2特点

1)顺序二叉树通常只考虑完全二叉树
       2)第n个元素的左子节点为2 * n + 1
       3)第n个元素的右子节点为 2 * n + 2
       4)第n个元素的父节点为 (n-1) / 2

5.3代码

//前序遍历
public void preOrder(int index) {System.out.println(arr[index]);if (2 * index + 1 < arr.length) {//相当于this.left != nullpreOrder(2 * index + 1);//preOrder(this.left)}if (2 * index + 2 < arr.length) {preOrder(2 * index + 2);}
}

6.线索化二叉树

难难~~,通过画图实际分析可以解决

6.1问题分析

上述的二叉树中有几个节点的左右指针,并没有完全的利用上。于是引入线索二叉树。

6.2基本介绍

1)n个结点的二叉链表中含有**n+1 [公式 2n-(n-1)=n+1]**个空指针域。利用二叉链表中的空指针域,存放指向该结点在某种遍历次序下的前驱和后继结点的指针(这种附加的指针称为"线索")。
       2)线索二叉树可分为前序线索二叉树、中序线索二叉树和后序线索二叉树三种
       3)一个结点的前一个结点,称为前驱结点
       4)一个结点的后一个结点,称为后继结点

6.3思路分析

1)线索化二叉树的思路分析
       无论是前序、中序、还是后序线索化二叉树,都需要:
       pre:表示当前结点node的前驱节点(如果node.left == null),node:表示当前节点,同时也是pre的后继结点(如果pre.right == null);
       leftTyperightType(默认为0)表示该节点是否进行了线索化。

2)遍历线索化二叉树的思路分析
       线索化后结点之间已经不是单向联系了,所以不能用递归的方式。

6.4代码

1)前序线索化及前序遍历

//前序遍历
public void preOrder(){HeroNode node = root;while (node != null){System.out.println(node);while (node.getLeftType() == 0){node = node.getLeft();System.out.println(node);}node = node.getRight();}
}//前序线索化
public void preThreadedTree(HeroNode node){if (node == null){return;}if (node.getLeft() == null){node.setLeft(pre);node.setLeftType(1);}if (pre != null && pre.getRight() == null){pre.setRight(node);pre.setRightType(1);}pre = node;if(node.getLeftType() != 1){preThreadedTree(node.getLeft());}if (node.getRightType() != 1){preThreadedTree(node.getRight());}
}

2)中序线索化及中序遍历

//中序遍历
public void midOrder(){HeroNode node = root;while (node != null){while (node.getLeftType() == 0){node = node.getLeft();}System.out.println(node);while (node.getRightType() == 1){node = node.getRight();System.out.println(node);}node = node.getRight();}
}//中序线索化
public void midThreadedTree(HeroNode node){if (node == null){return;}//左线索化midThreadedTree(node.getLeft());//前驱节点if (node.getLeft() == null){node.setLeft(pre);node.setLeftType(1);}//后继节点if (pre != null && pre.getRight() == null){pre.setRight(node);pre.setRightType(1);}pre = node;//右线索化midThreadedTree(node.getRight());
}

3)后序线索化及后序遍历

//后续遍历:代码有问题!!!!
public void postOrder(){HeroNode node = root;while (node.getLeftType() == 0){node = node.getLeft();}System.out.println(node);while (node.getRightType() == 1){node = node.getRight();System.out.println(node);}HeroNode node1 = root.getRight();while (node1.getLeftType() == 0){node1 = node1.getLeft();}System.out.println(node1);while (node1.getRightType() == 1){node1 = node1.getRight();System.out.println(node1);}
}//后序线索化
public void postThreadedTree(HeroNode node){if (node == null){return;}postThreadedTree(node.getLeft());postThreadedTree(node.getRight());if (node.getLeft() == null){node.setLeft(pre);node.setLeftType(1);}if (pre != null && pre.getRight() == null){pre.setRight(node);pre.setRightType(1);}pre = node;
}

总结

To be continued~~,堆排序,赫夫曼树,赫夫曼编码

数据结构与算法weeks03相关推荐

  1. Python3-Cookbook总结 - 第一章:数据结构和算法

    第一章:数据结构和算法 Python 提供了大量的内置数据结构,包括列表,集合以及字典.大多数情况下使用这些数据结构是很简单的. 但是,我们也会经常碰到到诸如查询,排序和过滤等等这些普遍存在的问题. ...

  2. 推荐一个关于.NET平台数据结构和算法的好项目

    http://www.codeplex.com/NGenerics 这是一个类库,它提供了标准的.NET框架没有实现的通用的数据结构和算法.值得大家研究. 转载于:https://www.cnblog ...

  3. 数据结构和算法:(3)3.1线性表的顺序存储结构

    -----------------------1.线性表基础操作------------------------ 线性表:(List)由零个或多个数据元素组成的有限序列. 首先他是一个序列,元素之间是 ...

  4. weiss数据结构和算法书的使用说明

    <数据结构与算法分析 C语言描述>Mark Allen Weiss著,冯舜玺译,机械工业出版社.Weiss教授的经典教材三部曲之一,其中的C语言描述版本,也就是本书,被称为20世纪最重要的 ...

  5. 数据结构和算法 -- 学习导图

    数据结构和算法 是作为程序员写出高效代码的基础,为了今后的两年在高效代码之路上持续精进,将按照此学习导图进行 算法和数据结构的刻意练习,同时也希望为同样有高效代码追求的伙伴们提供一条学习路径,共同进步 ...

  6. Java数据结构与算法(第四章栈和队列)

    2019独角兽企业重金招聘Python工程师标准>>> 本章涉及的三种数据存储类型:栈.队列和优先级队列. 不同类型的结构 程序员的工具 数组是已经介绍过的数据存储结构,和其他结构( ...

  7. python数据结构与算法总结

    python常用的数据结构与算法就分享到此处,本月涉及数据结构与算法的内容有如下文章: <数据结构和算法对python意味着什么?> <顺序表数据结构在python中的应用> ...

  8. 学习JavaScript数据结构与算法(一):栈与队列

    本系列的第一篇文章: 学习JavaScript数据结构与算法(一),栈与队列 第二篇文章:学习JavaScript数据结构与算法(二):链表 第三篇文章:学习JavaScript数据结构与算法(三): ...

  9. MySQL索引背后的数据结构及算法原理【转】

    http://blog.codinglabs.org/articles/theory-of-mysql-index.html MySQL索引背后的数据结构及算法原理[转] 摘要 本文以MySQL数据库 ...

最新文章

  1. 简单的短信验证功能的实现
  2. 从零到百亿互联网金融架构发展史---架构变迁
  3. 装了BT5后要做的几件事
  4. 产品问答 | 入职一家公司,你的选择依据是什么?
  5. dubbo mysql_dubbo系列(四) 凑一下热闹 使用dubbo redis mybatis mysql 实现商品秒杀功能...
  6. SAP云平台里的日志系统概述
  7. 【需求工程】需求管理
  8. oracle导出dmp空表导不出来,如何解决Oracle11g使用dmp命令无法导出空表问题
  9. java 与 区别
  10. 原生js的ajax的get怎么传参,原生js---ajax---get方法传数据
  11. python骗局-python 无良培训忽悠骗局知多少?
  12. [Python] 中英文标点转换
  13. 筛选索引--filter indexs
  14. 快速学习nodejs系列:四、nodejs特性1--单线程
  15. linux 安装talib
  16. 华为交换机冗余链路(VRRP)和vlan负载均衡
  17. 彻底删除顽固dll文件
  18. 魔兽7.0服务器维护时间,关于魔兽7.0版本你一定要知道的60条注意事项
  19. 二叉树——推荐一些神奇的网站
  20. WINDWOS XP应用大全

热门文章

  1. RabbitMQ初探
  2. 360浏览器边看边录功能在哪里打开?
  3. 开源扫描仪图片管理软件
  4. Unity-2D游戏-打击感与敌人AI
  5. 中国摩托车国内外进出口数据和分析2018-2020
  6. 荧光素FITC标记多糖,FITC-polysaccharide
  7. 全民付手机接口开发生产环境error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol
  8. 工作邦智慧水务营收系统
  9. 为什么MySQL的浮点数类型不够精准?(实例证明)
  10. 钉钉企业应用开发指南