Java实现遍历、排序、查找算法及简要说明
java顺序遍历最快算法

java顺序遍历最快算法1.引言1.1 概述随着计算机科学的发展,算法的优化一直是重要的研究方向之一。
在Java语言中,对于数据结构的遍历操作尤为重要。
一种常见的需求是对某个数据集合进行顺序遍历,即按照数据元素在集合中的位置依次进行访问。
本文旨在探讨如何实现一种效率更高的Java顺序遍历算法。
通过对目前已有的遍历算法进行分析和比较,我们提出了一种新的算法。
该算法结合了一些优化技巧,并在实现细节上进行了一些改进,以提高遍历效率。
我们将详细介绍该算法的原理和实现细节,并通过实验对其性能进行评估。
通过这篇文章,读者将了解到Java中顺序遍历的重要性,以及如何通过优化算法来提高遍历操作的效率。
同时,我们也展望了未来在这个领域可能的研究方向,希望能够为相关领域的学者和开发人员提供一些借鉴和启发。
接下来,我们将首先介绍文章的整体结构,让读者对本文有一个大致的了解。
1.2 文章结构本文主要介绍java中的顺序遍历算法,并提出一种能够实现最快遍历效果的新算法。
文章将从以下几个方面展开讨论:第一部分:引言在引言部分,我们将简要概述本文的主要内容和目的,并介绍本文的结构安排。
第二部分:背景介绍在背景介绍部分,我们将介绍java的顺序遍历算法的重要性和应用场景。
同时,我们也将探讨目前已存在的一些遍历算法,并分析它们的优缺点。
第三部分:提出的新算法这一部分是本文的核心内容。
我们将提出一种新的顺序遍历算法,该算法能够在效率上实现最优化。
我们将详细阐述该算法的原理和关键思想,并进行算法的设计和实现。
第四部分:算法实现细节在这一部分,我们将深入探讨新算法的实现细节。
我们将介绍算法所依赖的数据结构和算法的时间复杂度。
同时,我们还将给出算法的伪代码,并通过实例演示算法的运行过程。
第五部分:结论在结论部分,我们将对整篇文章进行总结,概述本文的主要贡献和创新点。
同时,我们将评估新算法的效果,并讨论可能的改进和未来发展方向。
通过以上结构,本文将全面介绍java顺序遍历算法的现状和挑战,并提出一种能够实现最快遍历效果的新算法。
Java常见的七种查找算法

Java常见的七种查找算法1. 基本查找也叫做顺序查找,说明:顺序查找适合于存储结构为数组或者链表。
基本思想:顺序查找也称为线形查找,属于无序查找算法。
从数据结构线的一端开始,顺序扫描,依次将遍历到的结点与要查找的值相比较,若相等则表示查找成功;若遍历结束仍没有找到相同的,表示查找失败。
示例代码:public class A01_BasicSearchDemo1 {public static void main(String[] args){//基本查找/顺序查找//核心://从0索引开始挨个往后查找//需求:定义一个方法利用基本查找,查询某个元素是否存在//数据如下:{131, 127, 147, 81, 103, 23, 7, 79}int[] arr ={131,127,147,81,103,23,7,79};int number =82;System.out.println(basicSearch(arr, number));}//参数://一:数组//二:要查找的元素//返回值://元素是否存在public static boolean basicSearch(int[] arr,int number){//利用基本查找来查找number在数组中是否存在for(int i =0; i < arr.length; i++){if(arr[i]== number){return true;}}return false;}}2. 二分查找也叫做折半查找,说明:元素必须是有序的,从小到大,或者从大到小都是可以的。
如果是无序的,也可以先进行排序。
但是排序之后,会改变原有数据的顺序,查找出来元素位置跟原来的元素可能是不一样的,所以排序之后再查找只能判断当前数据是否在容器当中,返回的索引无实际的意义。
基本思想:也称为是折半查找,属于有序查找算法。
用给定值先与中间结点比较。
比较完之后有三种情况:•相等说明找到了•要查找的数据比中间节点小说明要查找的数字在中间节点左边•要查找的数据比中间节点大说明要查找的数字在中间节点右边代码示例:package com.itheima.search;public class A02_BinarySearchDemo1 {public static void main(String[] args){//二分查找/折半查找//核心://每次排除一半的查找范围//需求:定义一个方法利用二分查找,查询某个元素在数组中的索引//数据如下:{7, 23, 79, 81, 103, 127, 131, 147}int[] arr ={7,23,79,81,103,127,131,147};System.out.println(binarySearch(arr,150));}public static int binarySearch(int[] arr,int number){//1.定义两个变量记录要查找的范围int min =0;int max = arr.length-1;//2.利用循环不断的去找要查找的数据while(true){if(min > max){return-1;}//3.找到min和max的中间位置int mid =(min + max)/2;//4.拿着mid指向的元素跟要查找的元素进行比较if(arr[mid]> number){//4.1 number在mid的左边//min不变,max = mid - 1;max = mid -1;}else if(arr[mid]< number){//4.2 number在mid的右边//max不变,min = mid + 1;min = mid +1;}else{//4.3 number跟mid指向的元素一样//找到了return mid;}}}}3. 插值查找在介绍插值查找之前,先考虑一个问题:为什么二分查找算法一定要是折半,而不是折四分之一或者折更多呢?其实就是因为方便,简单,但是如果我能在二分查找的基础上,让中间的mid点,尽可能靠近想要查找的元素,那不就能提高查找的效率了吗?二分查找中查找点计算如下:mid=(low+high)/2, 即mid=low+1/2*(high-low);我们可以将查找的点改进为如下:mid=low+(key-a[low])/(a[high]-a[low])*(high-low),这样,让mid值的变化更靠近关键字key,这样也就间接地减少了比较次数。
JAVA实现二叉树的前序遍历、中序遍历、后序遍历和层次遍历算法

本文由我司收集整编,推荐下载,如有疑问,请与我司联系JAVA 实现二叉树的前序遍历、中序遍历、后序遍历和层次遍历算法JAVA 实现二叉树的前序遍历、中序遍历、后序遍历和层次遍历算法如图所示一颗二叉树,用JAVA 实现二叉树的前序遍历、中序遍历、后序遍历和层次遍历算法定义树节点public class TreeNode { int data; TreeNode leftChild; TreeNode rightChild; TreeNode(){ this.leftChild=null; this.rightChild=null; this.data=-1; TreeNode(int data){ this.leftChild=null; this.rightChild=null; this.data=data; public TreeNode(int data, TreeNode leftChild, TreeNode rightChild) { this.data = data; this.leftChild = leftChild; this.rightChild = rightChild; //其它代码省略……二叉树的前序遍历、中序遍历、后序遍历和层次遍历算法设计package com.bean.binarytreedemo;import java.util.ArrayList;import java.util.LinkedList;import java.util.List;import java.util.Queue;import java.util.Stack; //给定一个一维数组,表示二叉树节点的值private int[] array = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; private static List TreeNode nodeList = null; public void createBinTree() { nodeList = new LinkedList TreeNode // 将一个数组的值依次转换为Node 节点for (int nodeIndex = 0; nodeIndex array.length; nodeIndex++) { nodeList.add(new TreeNode(array[nodeIndex])); // 对前lastParentIndex-1 个父节点按照父节点与孩子节点的数字关系建立二叉树for (int parentIndex = 0; parentIndex array.length / 2 - 1; parentIndex++) { // 左孩子nodeList.get(parentIndex).leftChild = nodeList .get(parentIndex * 2 + 1); // 右孩子nodeList.get(parentIndex).rightChild = nodeList .get(parentIndex * 2 + 2); // 最后一个父节点:因为最后一个父节点可能没有右孩子,因此单独拿出来处理int lastParentIndex = array.length / 2 - 1; // 左孩子nodeList.get(lastParentIndex).leftChild = nodeList .get(lastParentIndex * 2 + 1); // 右孩子,如果数组的长度为奇数才建立右孩子if (array.length % 2 == 1) {。
各种排序算法的分析及java实现

各种排序算法的分析及java实现排序一直以来都是让我很头疼的事,以前上《数据结构》打酱油去了,整个学期下来才勉强能写出个冒泡排序。
由于下半年要准备工作了,也知道排序算法的重要性(据说是面试必问的知识点),所以又花了点时间重新研究了一下。
排序大的分类可以分为两种:内排序和外排序。
在排序过程中,全部记录存放在内存,则称为内排序,如果排序过程中需要使用外存,则称为外排序。
下面讲的排序都是属于内排序。
内排序有可以分为以下几类:(1)、插入排序:直接插入排序、二分法插入排序、希尔排序。
(2)、选择排序:简单选择排序、堆排序。
(3)、交换排序:冒泡排序、快速排序。
(4)、归并排序(5)、基数排序一、插入排序•思想:每步将一个待排序的记录,按其顺序码大小插入到前面已经排序的字序列的合适位置,直到全部插入排序完为止。
•关键问题:在前面已经排好序的序列中找到合适的插入位置。
•方法:–直接插入排序–二分插入排序–希尔排序①直接插入排序(从后向前找到合适位置后插入)1、基本思想:每步将一个待排序的记录,按其顺序码大小插入到前面已经排序的字序列的合适位置(从后向前找到合适位置后),直到全部插入排序完为止。
2、实例3、java实现1package com.sort;23publicclass直接插入排序 {45publicstaticvoid main(String[] args) {6int[] a={49,38,65,97,76,13,27,49,78,34,12,64,1};7 System.out.println("排序之前:");8for (int i = 0; i < a.length; i++) {9 System.out.print(a[i]+" ");10 }11//直接插入排序12for (int i = 1; i < a.length; i++) {13//待插入元素14int temp = a[i];15int j;16/*for (j = i-1; j>=0 && a[j]>temp; j--) {17 //将大于temp的往后移动一位18 a[j+1] = a[j];19 }*/20for (j = i-1; j>=0; j--) {21//将大于temp的往后移动一位22if(a[j]>temp){23 a[j+1] = a[j];24 }else{25break;26 }27 }28 a[j+1] = temp;29 }30 System.out.println();31 System.out.println("排序之后:");32for (int i = 0; i < a.length; i++) {33 System.out.print(a[i]+" ");34 }35 }3637 }4、分析直接插入排序是稳定的排序。
Java程序设计中的查找与排序算法实现案例

Java程序设计中的查找与排序算法实现案例在Java程序设计中,查找与排序算法是非常重要的部分。
它们能够对数据进行快速、高效的操作,提高程序的执行效率。
本文将介绍几种常用的查找与排序算法,并给出相应的Java实现案例。
一、查找算法1. 顺序查找顺序查找是一种简单直接的查找算法。
它从数据集合的起始位置开始逐个比较,直到找到目标元素或者遍历完整个数据集合。
以下是顺序查找的Java实现案例:```javapublic int sequentialSearch(int[] array, int target) {for (int i = 0; i < array.length; i++) {if (array[i] == target) {return i;}}return -1;}```2. 二分查找二分查找是一种高效的查找算法,但要求数据集合是有序的。
它通过重复将数据集合分成两部分,并判断目标元素在哪一部分中,从而在每次比较中减少一半的数据量。
以下是二分查找的Java实现案例:```javapublic int binarySearch(int[] array, int target) {int left = 0;int right = array.length - 1;while (left <= right) {int mid = (left + right) / 2;if (array[mid] == target) {return mid;} else if (array[mid] < target) {left = mid + 1;} else {right = mid - 1;}}return -1;```二、排序算法1. 冒泡排序冒泡排序是一种简单直观的排序算法,它通过多次遍历数据集合,每次比较相邻两个元素并进行交换,将大的元素逐渐向后移动,达到排序的目的。
以下是冒泡排序的Java实现案例:```javapublic void bubbleSort(int[] array) {int n = array.length;for (int i = 0; i < n - 1; i++) {for (int j = 0; j < n - i - 1; j++) {if (array[j] > array[j + 1]) {int temp = array[j];array[j] = array[j + 1];array[j + 1] = temp;}}}```2. 快速排序快速排序是一种常用的排序算法,它采用分治的思想。
java 常用算法总结 -回复

java 常用算法总结-回复Java常用算法总结在Java程序开发中,算法是非常重要的一部分,它们能够解决各种问题,并为程序提供高效的解决方案。
本文将总结Java中常用的算法,并为每种算法的主题进行详细解释。
以下是本文的主要内容:1. 基础算法:涵盖了常见的算法思想和数据结构,例如递归、排序、查找等。
1.1 递归:递归是一种调用自身的算法。
它常用于解决可以被分解为规模较小的子问题的问题。
1.2 排序算法:排序算法用于对一组数据进行排序,常见的算法包括冒泡排序、插入排序、选择排序、快速排序、归并排序等。
1.3 查找算法:查找算法用于在一组数据中查找指定的元素,常见的算法包括线性查找、二分查找、哈希查找等。
2. 图算法:图算法用于解决与图相关的问题,例如找到两个节点之间的最短路径、判断图是否连通等。
2.1 广度优先搜索(BFS):BFS算法用于在图中寻找最短路径。
它从给定的起始节点开始,逐层遍历图中的节点,直到找到目标节点或遍历完所有节点。
2.2 深度优先搜索(DFS):DFS算法用于在图中寻找路径。
它从给定的起始节点开始,沿着一条路径一直遍历直到不能继续才回溯,继续遍历其他路径。
2.3 最小生成树(MST):最小生成树算法用于在给定的图中找到一棵包含所有节点的树,并使得树的所有边的权重之和最小。
2.4 拓扑排序:拓扑排序算法用于对有向无环图进行排序。
它将图中的节点按照依赖关系进行排序,使得每个依赖关系的节点都排在其依赖的节点之后。
3. 动态规划:动态规划是一种通过将问题分解为子问题并解决子问题来解决复杂问题的算法。
它通常用于解决最优化问题。
3.1 斐波那契数列:斐波那契数列是一个经典的动态规划问题,它的定义为f(n) = f(n-1) + f(n-2),其中f(0) = 0,f(1) = 1。
3.2 背包问题:背包问题是一个经典的动态规划问题,它的目标是在给定的背包容量下,将价值最大化。
常见的背包问题包括01背包问题、完全背包问题和多重背包问题。
【Java数据结构】前序遍历、中序遍历、后续遍历图解以及算法

【Java数据结构】前序遍历、中序遍历、后续遍历图解以及算法前序遍历、中序遍历、后续遍历图解以及算法概述:本⽂包含以下算法,⼤部分以递归实现前序遍历(中左右):先输出⾃⼰,然后是左孩⼦,最后右孩⼦;中序遍历(左中右):先输出左孩⼦,然后是⾃⼰,最后右孩⼦;后序遍历(左右中):先输出左孩⼦,然后是右孩⼦,最后⾃⼰;层次遍历:⼀层⼀层从上到下从左到右遍历;前序遍历和中序遍历确定⼀棵⼆叉树;后序遍历和中序遍历确定⼀棵⼆叉树;前序遍历和后续遍历其中⼀种加上中序遍历,便可以确定⼀颗⼆叉树;以下是关于遍历的算法1public class Main {2public static void main(String[] args) {3/*4⽣成⼆叉树5 06 1 27 3 4 5 68前序遍历为: 01342569中序遍历为: 314052610后序遍历为: 341562011*/12 TreeNode[] tree = new TreeNode[7];13for (int i = 0; i < 7; i++) {14 tree[i] = new TreeNode(i);15 }1617for (int i = 0; i < 7; i++) {18if(i*2+1 < 7){19 tree[i].left = tree[i*2+1];20 }21if(i*2+2 <7){22 tree[i].right = tree[i*2+2];23 }24 }25 System.out.println("前序遍历的结果:");26 preOrder(tree[0]);27 System.out.println("\n后序遍历的结果:");28 afterOrder(tree[0]);29 System.out.println("\n中序遍历的结果:");30 infixOrder(tree[0]);31 System.out.println("\n层次遍历的结果:");32 levelOrder(tree[0]);33 System.out.println("\n⼆叉树的深度为:");34 System.out.println(getTreeDepth(tree[0]));35int[] pre = {0,1,3,4,2,5,6};36int[] in= {3,1,4,0,5,2,6};37int[] after = {3,4,1,5,6,2,0};38 Main main = new Main();39 TreeNode root1 = main.getTreeByPreAndInfix(pre,in);40 System.out.println("重建后的树的中序遍历为:");41 infixOrder(root1);42 TreeNode root2 = main.getTreeByAfterAndInfix(after,in);43 System.out.println("\n重建后的树的中序遍历为:");44 infixOrder(root2);4546 }4748/**49 * 递归实现打印⼆叉树的前序遍历结果50 * @param root ⼆叉树的根节点51*/52public static void preOrder(TreeNode root){53if(root==null){54return;55 }56 System.out.print(root.val+" ");57 TreeNode left = root.left;58 TreeNode right = root.right;59if(left != null){60 preOrder(left);61 }62if(right != null){63 preOrder(right);64 }65 }6667/**68 * 递归实现打印⼆叉树的中序遍历结果69 * @param root ⼆叉树的根节点70*/71public static void infixOrder(TreeNode root){72if(root==null){73return;74 }75 TreeNode left = root.left;76 TreeNode right = root.right;77if(left != null){78 infixOrder(left);79 }80 System.out.print(root.val+" ");81if(right != null){82 infixOrder(right);83 }84 }8586/**87 * 递归实现打印⼆叉树的后序遍历88 * @param root ⼆叉树的根节点89*/90public static void afterOrder(TreeNode root){91if(root==null){92return;93 }94 TreeNode left = root.left;95 TreeNode right = root.right;96if(left != null){97 afterOrder(left);98 }99if(right != null){100 afterOrder(right);101 }102 System.out.print(root.val+" ");103 }104105/**106 * 层次遍历⼀个⼆叉树107 * @param root ⼆叉树的根节点108*/109public static void levelOrder(TreeNode root){110if(root==null){111return;112 }113 LinkedList<TreeNode> list = new LinkedList<>();114 list.add(root);115 TreeNode temp;116while (!list.isEmpty()){117 temp = list.poll();118 System.out.print(temp.val+" ");119if(temp.left!=null){120 list.add(temp.left);121 }122if(temp.right!=null){123 list.add(temp.right);124 }125 }126127 }128129 HashMap<Integer,Integer> map = new HashMap<>(); 130int[] pre;131/**132 * 通过前序遍历和中序遍历确定⼀棵⼆叉树133 * @param pre 前序遍历结果数组134 * @param infix 中序遍历结果数组135*/136public TreeNode getTreeByPreAndInfix(int[] pre, int[] infix){137this.pre = pre;138for (int i = 0; i < pre.length; i++) {139 map.put(infix[i],i);140 }141return recur(0,0,infix.length-1);142 }143144/**145 * 前序和中序递归算法,思路是在中序遍历中确定左⼦树和右⼦树,同时确定左⼦树和右⼦树的根节点146 * 根节点肯定是在前序遍历中找,但是找根节点需要确定左右⼦树的长度147 * 左⼦树的根节点等于当前根节点+1148 * 右⼦树的根节点等于当前根节点+左⼦树的长度+1149 * 要确定长度,就要在中序遍历中找到上⼀个根节点的位置和树的左边界和右边界150 * @param pre_root 前序遍历中根节点在数组中你的索引值151 * @param in_left 当前树中序遍历中的左边界152 * @param in_right 当前树中序遍历的有边界153 * @return根节点154*/155 TreeNode recur(int pre_root,int in_left,int in_right){156//如果这颗树的左边界⼤于右边界,证明上⼀个节点是叶⼦节点,直接返回空157if(in_left>in_right){158return null;159 }160//上⼀个节点不是叶⼦节点,则创建⼦树的根节点161 TreeNode root = new TreeNode(pre[pre_root]);162//获得这个根节点在前序遍历中的下标163int i = map.get(pre[pre_root]);164//递归左⼦树,左⼦树的左边界和上⼀个节点的左边界⼀致,右边界为根节点在中序遍历中的下标减⼀165 root.left = recur(pre_root+1,in_left,i-1);166//递归右⼦树,右⼦树的根节点在前序遍历中的下标为前⼀个根节点+左⼦树的长度(right-left)+1167 root.right = recur(pre_root+(i-in_left)+1,i+1,in_right);168return root;169 }170171172 HashMap<Integer,Integer> map2 = new HashMap<>();173int[] after;174175/**176 * 通过后序遍历和中序遍历确定⼀棵⼆叉树177 * @param after 后序遍历结果数组178 * @param infix 中序遍历结果数组179*/180public TreeNode getTreeByAfterAndInfix(int[] after,int[] infix){181this.after = after;182for (int i = 0; i < infix.length; i++) {183 map2.put(infix[i],i);184 }185return recur2(after.length-1,0,after.length-1);186 }187188/**189 * 在中序遍历中确定每⼀棵⼦树的根节点190 * @param after_root 在后序遍历中根节点的下标191 * @param in_left 在中序遍历中当前树的左边界192 * @param in_right 在中序遍历中当前树的有边界193 * @return当前树的根节点194*/195 TreeNode recur2(int after_root,int in_left,int in_right){196//这棵⼦树的左边界⼤于有边界,证明这颗⼦树是叶⼦节点197if(in_left>in_right){198return null;199 }200//不是叶⼦节点,创建这颗⼦树的根节点201 TreeNode root = new TreeNode(after[after_root]);202//获得当前根节点在中序遍历中的下标203int i = map2.get(after[after_root]);204//递归右⼦树,右⼦树的左边界在中序遍历中的下标是上⼀个根节点下标加⼀,右边界不变205 root.right = recur2(after_root-1,i+1,in_right);206//递归左⼦树,左⼦树的根节点在后序遍历的位置=上⼀个的下标-右⼦树的长度-1,左边界不变,右边界等于上⼀个节点的下标-1 207 root.left = recur2(after_root-(in_right-i)-1,in_left,i-1);208return root;209 }210211/**212 * 获得⼆叉树的深度213 * @param root ⼆叉树的根节点214 * @return⼆叉树深度215*/216public static int getTreeDepth(TreeNode root){217if(root ==null){218return 0;219 }220int left = getTreeDepth(root.left);221int right = getTreeDepth(root.right); 222if(left>right){223return left+1;224 }else {225return right+1;226 }227 }228 }229230class TreeNode{231public int val;232public TreeNode left;233public TreeNode right;234235public TreeNode(int val) {236this.val = val;237 }238 }。
java遍历二叉树的三种方法

java遍历二叉树的三种方法在Java中,遍历二叉树通常有三种方法:前序遍历、中序遍历和后序遍历。
这三种方法都是通过递归实现的,并且每种遍历方法都具有不同的应用场景和特点。
首先,我们来介绍前序遍历。
前序遍历的顺序是先访问根节点,然后递归遍历左子树,最后递归遍历右子树。
这种遍历方法常用于打印表达式、复制二叉树等场景。
下面是前序遍历的Java代码实现:```javapublic void preorderTraversal(TreeNode root) {if (root != null) {System.out.println(root.val); // 访问根节点preorderTraversal(root.left); // 递归遍历左子树preorderTraversal(root.right); // 递归遍历右子树}}```接下来,我们介绍中序遍历。
中序遍历的顺序是先递归遍历左子树,然后访问根节点,最后递归遍历右子树。
这种遍历方法常用于二叉搜索树的查找操作,因为中序遍历可以得到有序的结果。
下面是中序遍历的Java代码实现:```javapublic void inorderTraversal(TreeNode root) {if (root != null) {inorderTraversal(root.left); // 递归遍历左子树System.out.println(root.val); // 访问根节点inorderTraversal(root.right); // 递归遍历右子树}}```最后,我们介绍后序遍历。
后序遍历的顺序是先递归遍历左子树,然后递归遍历右子树,最后访问根节点。
这种遍历方法常用于计算二叉树的深度、判断是否为平衡二叉树等场景。
下面是后序遍历的Java代码实现:```javapublic void postorderTraversal(TreeNode root) {if (root != null) {postorderTraversal(root.left); // 递归遍历左子树postorderTraversal(root.right); // 递归遍历右子树System.out.println(root.val); // 访问根节点}}```除了递归方法外,我们还可以使用栈来实现二叉树的遍历。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1.遍历算法(遍历二叉树6种方法)1.1.概述遍历算法针对二叉树而言的,主要有先序、中序、后序三种遍历顺序,三种顺序又分别有递归和常规算法,二叉树遍历的主要思想是:遍历左子树,遍历右子树,访问根节点,由这三者的遍历顺序来确定是先序、中序还是后序。
下面只要求掌握递归遍历算法,常规遍历算法见附录一。
1.2.先序遍历算法遍历顺序:访问根节点,遍历左子树,遍历右子树。
代码如下:void preOrder(BinaryTreeNode bt) {if (bt == null)// 如果当前树为空,则终止递归return;System.out.print(bt.getData());// 先访问根节点preOrder(bt.getLeftChild());// 再遍历左子树preOrder(bt.getRightChild());// 再遍历右子树}1.3.中序遍历算法遍历顺序:遍历左子树,访问根节点,遍历右子树。
代码如下:void midOrder(BinaryTreeNode bt) {if (bt == null)// 如果当前树为空,则终止递归return;preOrder(bt.getLeftChild());// 先遍历左子树System.out.print(bt.getData());// 再访问根节点preOrder(bt.getRightChild());// 再遍历右子树}1.4.后序遍历算法遍历顺序:遍历左子树,遍历右子树,访问根节点。
代码如下:void postOrder(BinaryTreeNode bt) {if (bt == null)// 如果当前树为空,则终止递归return;preOrder(bt.getLeftChild());// 先遍历左子树preOrder(bt.getRightChild());// 再遍历右子树System.out.print(bt.getData());// 再访问根节点}1.5.层次遍历算法void levelOrder(BinaryTreeNode bt) {if (bt == null)return;Queue q = new ArrayQueue();q.enqueue(bt);while (!q.isEmpty()) {bt = (BinaryTreeNode) q.dequeue();// 取出队首元素,访问之System.out.println(bt.getData());if (bt.hasLeftChild()) {q.enqueue(bt.getLeftChild());// 如果左节点存在,放入队列中}if (bt.hasRightChild()) {q.enqueue(bt.getRightChild());// 如果右节点存在,放入队列中}}}2.排序算法(9种排序算法)2.1.概述将一个数据元素的任意序列,重新排列成一个按关键字有序的序列。
2.2.插入类排序基本思想是:逐个考察每个待排序元素,将每一个新元素插入到前面已经排好序的序列中适当的位置上,使得新序列仍然是一个有序序列。
主要介绍三种:直接插入排序、折半插入排序和希尔排序。
2.2.1.直接插入排序思路:仅有一个元素的序列总是有序的,因此,对n 个记录的序列,可从第二个元素开始直到第n 个元素,逐个向有序序列中执行插入操作,从而得到n 个元素按关键字有序的序列。
代码如下:void insert(int[] a) {for (int i = 1; i < a.length; i++) {// 从第二个开始比较插入// 待插入的元素比之前排好序的元素最大值小才需要插入if (a[i] < a[i - 1]) {int tmp = a[i];// 把当前位置腾出来a[i] = a[i - 1];// 和已排好序的最大值交换顺序int j = i - 2;// 遍历之前i-2个元素找出要插入的位置// 如果待插入元素小于已排好序中的第j位并j不小于0则继续遍历for (; j >= 0 && tmp < a[j]; j--)a[j + 1] = a[j];a[j + 1] = tmp;// j + 1即为待插入位置}2.2.2.折半插入排序思路:可以不断二分有序序列来确定插入位置,即搜索插入位置的方法可以使用折半查找实现。
代码如下:void binaryInsert(int[] a) {for (int i = 1; i < a.length; i++) {// 从第二个开始比较插入// 待插入的元素比之前排好序的元素最大值小才需要插入if (a[i] < a[i - 1]) {int tmp = a[i];// 把当前位置腾出来a[i] = a[i - 1];// 和已排好序的最大值交换顺序int low = 0, high = i - 1, mid;//high=已排好序列的长度while (low < high) {mid = (low + high) / 2;if (tmp < a[mid])high = mid - 1;elselow = mid + 1;}int j = i - 2;// 遍历之前i-2个元素找出要插入的位置// 取high是因为经过while循环后high一定是不大于low的for (; j > high; j--)a[j + 1] = a[j];a[high + 1] = tmp;// high + 1即为待插入位置}}}2.2.3.希尔排序思路:首先将待排序的元素分为多个子序列,使得每个子序列的元素个数相对较少,对各个子序列分别进行直接插入排序,待整个待排序序列“基本有序”后,再对所有元素进行一次直接插入排序。
static void shell(int[] a) {int d = 1;// 定义步长值while (d <= a.length / 3)d = d * 3 + 1;// 根据数组长度生成步长终值for (; d > 0; d = (d - 1) / 3) {// 还原步长值for (int i = d; i < a.length; i++) {// 从第1个步长开始比较插入// 待插入的元素比之前排好序的元素最大值小才需要插入if (a[i] < a[i - d]) {int tmp = a[i];// 把当前位置腾出来a[i] = a[i - d];// 和已排好序的最大值交换顺序int j = i - d - 1;// 遍历之前i-d-1个元素找出要插入的位置// 如果待插入元素小于已排好序中的第j位并j不小于0则继续遍历for (; j >= 0 && tmp < a[j]; j -= d)a[j + d] = a[j];a[j + d] = tmp;// j + d即为待插入位置}}2.3.交换类排序2.3.1.基本思想交换类排序主要是通过两两比较待排元素的关键字,若发现与排序要求相逆,则“交换”之。
2.3.2.冒泡排序void bubble(int[] a) {for (int i = 0; i < a.length; i++) {// 先遍历数组for (int j = 1; j < a.length - i; j++) {// 遍历未排好序的len-i个元素if (a[j - 1] > a[j]) {// 前后比较int tmp = a[j - 1];a[j - 1] = a[j];a[j] = tmp;}}}}2.3.3.快速排序思路:划分步骤:通过枢轴元素 x 将序列一分为二,且左子序列的元素均小于 x,右子序列的元素均大于 x;治理步骤:递归的对左、右子序列排序;void quick(int[] a, int low, int high) {if (low < high) {int part = partition(a, low, high);quick(a, low, part - 1);quick(a, part + 1, high);}}int partition(int[] a, int low, int high) {int tar = a[low];while (low < high) {// 循环该段数据while (low < high && tar < a[high])// 先从高端开始查找high--;a[low] = a[high];// 交换数据while (low < high && tar > a[low])// 再从低端开始查找low++;a[high] = a[low];// 交换数据}a[low] = tar;// 重新设置枢轴return low;// 返回枢轴位置2.4.选择类排序2.4.1.概述每一趟从n-i+1 (i=1,2,…,n)个元素中选取一个关键字最小的元素作为有序序列中第i 个元素。
2.4.2.简单选择排序void recursionSort(int[] arr, int index) {// 递归选择排序if (index < arr.length) {for (int i = 0; i < arr.length; i++) {if (arr[index] < arr[i]) {int tmp = arr[index];arr[index] = arr[i];arr[i] = tmp;}}index++;recursionSort(arr, index);}}void commonSort(int[] arr) {// 简单选择排序for (int i = 0; i < arr.length; i++) {for (int j = i + 1; j < arr.length; j++) {if (arr[i] > arr[j]) {int tmp = arr[j];arr[j] = arr[i];arr[i] = tmp;}}}}2.4.3.树形选择排序和堆排序(附录二)2.5.并归排序排序思想:1.划分:将待排序的序列划分为大小相等(或大致相等)的两个子序列;2.治理:当子序列的规模大于1 时,递归排序子序列,如果子序列规模为1 则成为有序序列;3.组合:将两个有序的子序列合并为一个有序序列。
void msort(int[] a, int low, int high) {if (low < high) {msort(a, low, (high + low) / 2);msort(a, (high + low) / 2 + 1, high);//并归后半段merge(a, low, (high + low) / 2, high);//并归前半段}}void merge(int[] a, int p, int q, int r) {int[] b = new int[r - p + 1];int s = p;//并归a中p到q,q+1到r两个数组int t = q + 1;int k = 0;while (s <= q && t <= r)//并归交叉段if (a[s] < a[t])b[k++] = a[s++];elseb[k++] = a[t++];while (s <= q)//并归剩下的段b[k++] = a[s++];while (t <= r)b[k++] = a[t++];for (int i = 0; i < b.length; i++)a[p + i] = b[i];}2.6.各种排序之间的比较3.查找算法(3种查找算法)3.1.顺序查找int order(int[] array, int tar) {for (int i = 0; i < array.length; i++) {if (tar == array[i])return i + 1;}return -1;}3.2.折半查找int binRecursion(int[] array, int tar, int low, int high) {// 二分法查找递归int mid;if (low > high)return -1;mid = (high + low) / 2;if (tar == array[mid])return mid + 1;else if (tar > array[mid])binRecursion(array, tar, mid++, high);elsebinRecursion(array, tar, low, mid--);return -1;}int bin(int[] array, int tar) {// 二分法查找非递归int low = 0, high = array.length - 1, mid;while (low <= high) {mid = (low + high) / 2;if (array[mid] == tar)return mid + 1;else if (array[mid] < tar)low = mid + 1;elsehigh = mid - 1;}return -1;}3.3.二叉树查找BinaryTreeNode binaryTreeRecusion(BinaryTreeNode bt, Object tar) {// 二叉树递归查找算法if (bt == null)return new BinaryTreeNode("null");switch (pare(tar, bt.getData())) {case -1:// tar比data小就查找左子树return binaryTreeRecusion(bt.getLeftChild(), tar);case 1:// tar比data大就查找右子树return binaryTreeRecusion(bt.getRightChild(), tar);default:// 比较结果是0,tar和data相等就返回return bt;}}BinaryTreeNode binaryTree(BinaryTreeNode bt, Object tar) {// 二叉树非递归查找算法while (bt != null) {switch (pare(tar, bt.getData())) {case -1:// tar比data小就查找左子树return bt = bt.getLeftChild();case 1:// tar比data大就查找右子树return bt = bt.getRightChild();default:// 比较结果是0,tar和data相等就返回return bt;}}return new BinaryTreeNode("null");}4.附录一void preOrder(BinaryTreeNode p) {// 二叉树先序遍历非递归算法Stack s = new SingleLinkedStack();while (p != null) {while (p != null) {System.out.println(p.getData());// 访问根节点if (p.hasRightChild()) {// 右子树压栈s.push(p.getRightChild());}p = p.getLeftChild();// 继续访问左子树直到为空}if (!s.isEmpty()) {p = (BinaryTreeNode) s.pop();// 当当前左子树遍历完成,存右子树的栈退栈}}}BinaryTreeNode goFarLeft(BinaryTreeNode bt, Stack s) {// 找到最左节点if (bt == null)return null;while (bt.hasLeftChild()) {s.push(bt);bt = bt.getLeftChild();}return bt;}void midOrder(BinaryTreeNode bt) {// 二叉树中序遍历的非递归算法Stack s = new SingleLinkedStack();BinaryTreeNode p = goFarLeft(bt, s);// 找到最左节点// 如果最左节点不为空则继续查找while (p != null) {System.out.println(p.getData());// 访问根节点if (p.hasRightChild()) {// 如果有右孩子节点,则访问有孩子节点的最左孩子节点p = goFarLeft(p.getRightChild(), s);} else if (!s.isEmpty()) {// 如果没有右孩子节点且栈不为空,则弹栈往回找上一级p = (BinaryTreeNode) s.pop();} elsep = null;// 栈为空则查找完成}}void lastOrder(BinaryTreeNode p) {// 二叉树后序遍历非递归算法Stack s = new SingleLinkedStack();BinaryTreeNode pre = null;// 缓存上次访问节点// 如果最左节点不为空则继续查找while (p != null || !s.isEmpty()) {while (p != null) {// 查找最左节点s.push(p);p = p.getLeftChild();}if (!s.isEmpty()) {// 取出栈顶节点p = (BinaryTreeNode) s.peek();// 判断当前节点是否是父亲节点的右子节点,如果是// 只需访问其父节点即可完成以p的父节点为根节点的子树的访问if (!p.hasRightChild() || p.getRightChild() == pre) { list.insertLast(p);s.pop();pre = p;p = null;} elsep = p.getRightChild();}5.附录二堆排序:// 已知 r[low..high]中除 r[low]之外,其余元素均满足堆的定义private void heapAdjust(int[] r, int low, int high) {int tmp = r[low];for (int j = 2 * low; j <= high; j = j * 2) { // 沿关键之较大的元素向下进行筛选if (j < high && r[j] > r[j + 1])// j 指向关键之较大的元素j++;if (tmp >= r[j])// 若 temp 比其孩子都大,则插入到 low 所指位置break;r[low] = r[j];low = j; // 向下筛选}r[low] = tmp;}public void heapSort(int[] r) {int n = r.length - 1;for (int i = n / 2; i >= 1; i--)// 初始化建堆heapAdjust(r, i, n);for (int i = n; i > 1; i--) { // 不断输出堆顶元素并调整 r[1..i-1]为新堆int tmp = r[1]; // 交换堆顶与堆底元素r[1] = r[i];r[i] = tmp;heapAdjust(r, 1, i - 1); // 调整}}。