数组 队列 链表 栈
线性结构作为最常用的数据结构,特点:数据元素之间一对一的线性关系
线性结构有两种不同的存储结构,顺序结构和链式结构
顺序结构线性表是顺序表,顺序表存储元素连续
链式存储线性表称为链表,链表中的存储元素不一定连续,元素节点中存放元素和相邻元素地址信息
二维数组,多维数组,广义表,树结构,图结构
基本介绍
一个数组大部分元素是0,或者同一个值的数组,使用稀疏数组来保存该数组
稀疏数组处理:
二维数组转稀疏数组思路:
稀疏数组转二维数组思路:
package com.fu.datastruct;
public class SparseArr {
public static void main(String[] args) {
int sum = 0;
//输出二维数组
int[][] chessArr1 = new int[11][11];
chessArr1[3][3] = 4;
chessArr1[4][4] = 5;
for (int[] c1 : chessArr1) {
for (int c2 : c1) {
System.out.printf("%d\t",c2);
if (c2 != 0){
sum+=1;
}
}
System.out.println();
}
System.out.println("有效值:"+sum);
//二维数组转稀疏数组
System.out.println("输出稀疏数组~~");
int[][] sparseArr = new int[sum + 1][3];
sparseArr[0][0] = 11;
sparseArr[0][1] = 11;
sparseArr[1][1] = sum;
int count = 0;
for (int i = 0; i < chessArr1.length; i++) {
for (int j = 0; j < chessArr1[i].length; j++) {
if (chessArr1[i][j] != 0){
count++;
sparseArr[count][0] = i;
sparseArr[count][1] = j;
sparseArr[count][2] = chessArr1[i][j];
}
}
}
for (int[] s1 : sparseArr) {
for (int s2 : s1) {
System.out.printf("%d\t",s2);
}
System.out.println();
}
System.out.println("输出二维数组~~");
int[][] chessArr2 = new int[sparseArr[0][0]][sparseArr[0][1]];
for (int i = 1; i < sparseArr.length; i++) {
chessArr2[sparseArr[i][0]][sparseArr[i][1]] = sparseArr[i][2];
}
for (int[] c1 : chessArr2) {
for (int c2 : c1) {
System.out.printf("%d\t",c2);
}
System.out.println();
}
}
}
package com.fu.datastruct.queue;
import java.util.Scanner;
public class ArrayQueueDemo {
public static void main(String[] args) {
ArrayQueue queue = new ArrayQueue(3);
char key = ' ';
Scanner scanner = new Scanner(System.in);
boolean loop = true;
while(loop){
System.out.println("s(show) 显示队列");
System.out.println("e(exit) 退出队列");
System.out.println("a(add) 添加数据到队列");
System.out.println("g(get) 从队列取出数据");
System.out.println("h(head) 查看队列头数据");
key = scanner.next().charAt(0);
switch (key){
case 'a':
int i = scanner.nextInt();
queue.addQueue(i);
break;
case 'g':
try {
int r = queue.getQueue();
System.out.println("取出的数是:" + r);
} catch (Exception e) {
e.getMessage();
}
break;
case 's':
queue.showQueue();
break;
case 'h':
try {
int h = queue.headQueue();
System.out.println("取出的数是:" + h);
} catch (Exception e) {
e.getMessage();
}
break;
case 'e':
scanner.close();
loop = false;
break;
default:
break;
}
}
System.out.println("退出程序~~");
}}
class ArrayQueue{
private int maxSize;
private int front;
private int rear;
private int []arr;
public ArrayQueue(int arrMaxSize) {
maxSize = arrMaxSize;
front = -1;
rear = -1;
arr = new int[maxSize];
}
public boolean isFull(){
return rear == maxSize -1;
}
public boolean isEmpty(){
return rear == front;
}
public void addQueue(int n){
if (isFull()){
System.out.println("队列已满,无法加入");
return;
}
rear++;
arr[rear] = n;
}
public int getQueue(){
if (isEmpty()){
throw new RuntimeException("队列为空,无法取出头数据");
}
front++;
return arr[front];
}
public void showQueue(){
if (isEmpty()){
System.out.println(("队列为空,无法取出头数据"));
}
for (int i = 0; i < arr.length; i++) {
System.out.printf("arr[%d]=%d\n",i,arr[i]);
}
}
public int headQueue(){
if (isEmpty()){
throw new RuntimeException("队列为空,无法取出头数据");
}
return arr[front + 1];
}
}
package com.fu.datastruct.queue;
import java.util.Scanner;
public class CircleQueueDemo {
public static void main(String[] args) {
CircleQueue queue = new CircleQueue(4);
char key = ' ';
Scanner scanner = new Scanner(System.in);
boolean loop = true;
while(loop){
System.out.println("s(show) 显示队列");
System.out.println("e(exit) 退出队列");
System.out.println("a(add) 添加数据到队列");
System.out.println("g(get) 从队列取出数据");
System.out.println("h(head) 查看队列头数据");
key = scanner.next().charAt(0);
switch (key){
case 'a':
int i = scanner.nextInt();
queue.addQueue(i);
break;
case 'g':
try {
int r = queue.getQueue();
System.out.println("取出的数是:" + r);
} catch (Exception e) {
e.getMessage();
}
break;
case 's':
queue.showQueue();
break;
case 'h':
try {
int h = queue.headQueue();
System.out.println("取出的数是:" + h);
} catch (Exception e) {
e.getMessage();
}
break;
case 'e':
scanner.close();
loop = false;
break;
default:
break;
}
}
System.out.println("退出程序~~");
}}
class CircleQueue{
private int maxSize;
private int front;
private int rear;
private int []arr;
public CircleQueue(int arrMaxSize) {
maxSize = arrMaxSize;
arr = new int[maxSize];
}
public boolean isFull(){
return (rear + 1) % maxSize == front;
}
public boolean isEmpty(){
return rear == front;
}
public void addQueue(int n){
if (isFull()){
System.out.println("队列已满,无法加入");
return;
}
arr[rear] = n;
rear = (rear + 1)%maxSize;
}
public int getQueue(){
if (isEmpty()){
throw new RuntimeException("队列为空,无法取出头数据");
}
int value = arr[front];
front = (front + 1 )%maxSize;
return value;
}
public void showQueue(){
if (isEmpty()){
System.out.println(("队列为空,无法取出头数据"));
}
for (int i = front; i < front + size(); i++) {
System.out.printf("arr[%d]=%d\n",i % maxSize,arr[i%maxSize]);
}
}
public int size(){
return (rear - front + maxSize) % maxSize;
}
public int headQueue(){
if (isEmpty()){
throw new RuntimeException("队列为空,无法取出头数据");
}
return arr[front];
}
}
- 链表是以节点的方式存储
- 每个节点包含data域 next域 指向下一个节点
- 各个节点不一定是连续存储
- 链表分带头结点的链表和没有头节点的链表,根据需求确定
package com.fu.datastruct.queue;
public class SingleLinkedListDemo {
public static void main(String[] args) {
HeroNode h1 = new HeroNode(1, "宋江", "及时雨");
HeroNode h2 = new HeroNode(2, "卢俊义", "玉麒麟");
HeroNode h3 = new HeroNode(3, "吴用", "智多星");
HeroNode h4 = new HeroNode(4, "林冲", "豹子头");
SingleLinkedList s = new SingleLinkedList();
s.addByOrder(h1);
s.addByOrder(h4);
s.addByOrder(h3);
s.addByOrder(h2);
s.list();
System.out.println();
s.del(1);
s.update(new HeroNode(2,"晁盖","托塔天王"));
s.list();
}
}
class SingleLinkedList{
private HeroNode head = new HeroNode(0,"","");
public void add(HeroNode heroNode){//添加一个heroNode
HeroNode temp = head;
while(true){
if (temp.next == null)break;
temp = temp.next;
}
temp.next = heroNode;
}
public void list(){
if (head == null) {
System.out.println("链表为空");
return;
}
HeroNode temp = head.next;
while (true){
if (temp == null){
return;
}
System.out.println(temp);
temp = temp.next;
}
}
public void addByOrder(HeroNode heroNode){
HeroNode temp = head;
boolean flag = false;
while(true){
if (temp.next == null)break;
else if (temp.next.no > heroNode.no)break;
else if (temp.next.no == heroNode.no){
flag = true;
break;
}
temp = temp.next;
}
if (flag){
System.out.println("准备的英雄编号" + heroNode.no + "已经存在了,不用在插入了");
}else {
heroNode.next = temp.next;
temp.next = heroNode;
}
}
public void update(HeroNode newHero){
if (head.next == null) {
System.out.println("链表为空");
return;
}
HeroNode temp = head.next;
boolean flag = false;
while(true){
if (temp == null){
break;
}
else if (temp.no == newHero.no){
flag = true;
break;
}
temp = temp.next;
}
if(flag){
temp.name = newHero.name;
temp.nickname = newHero.nickname;
}
else System.out.println("没有找到" + newHero.no + "编号英雄,不能修改");
}
public void del(int no){
HeroNode temp = head;
boolean flag = false;
while (true){
if (temp.next == null) {
break;
}
else if (temp.next.no == no){
flag = true;
break;
}
temp = temp.next;
}
if (flag){
temp.next = temp.next.next;
}else System.out.println("没有对应下标英雄,无法删除");
}
}
class HeroNode{
public int no;
public String name;
public String nickname;
public HeroNode next;
public HeroNode(int no, String name, String nickname) {
this.no = no;
this.name = name;
this.nickname = nickname;
}
@Override
public String toString() {
return "HeroNode{" +
"no=" + no +
", name='" + name + '\'' +
", nickname='" + nickname + '\'' +
'}';
}
}
package com.fu.datastruct.queue;
public class DoubleLinkedListDemo {
public static void main(String[] args) {
HeroNode2 h1 = new HeroNode2(1, "宋江", "及时雨");
HeroNode2 h2 = new HeroNode2(2, "吴用", "智多星");
HeroNode2 h3 = new HeroNode2(3, "公孙胜", "入云龙");
DoubleLinkedList d = new DoubleLinkedList();
d.add(h1);
d.add(h2);
d.add(h3);
d.list();
d.add(new HeroNode2(4 , "戴宗","神行太保"));
d.list();
}
}
class DoubleLinkedList{
private HeroNode2 head = new HeroNode2(0,"","");
public void add(HeroNode2 heroNode){//添加一个heroNode
HeroNode2 temp = head;
while(true){
if (temp.next == null)break;
temp = temp.next;
}
temp.next = heroNode;
heroNode.pre = temp;
}
public void list(){
if (head == null) {
System.out.println("链表为空");
return;
}
HeroNode2 temp = head.next;
while (true){
if (temp == null){
return;
}
System.out.println(temp);
temp = temp.next;
}
}
public void update(HeroNode2 newHero){
if (head.next == null) {
System.out.println("链表为空");
return;
}
HeroNode2 temp = head.next;
boolean flag = false;
while(true){
if (temp == null){
break;
}
else if (temp.no == newHero.no){
flag = true;
break;
}
temp = temp.next;
}
if(flag){
temp.name = newHero.name;
temp.nickname = newHero.nickname;
}
else System.out.println("没有找到" + newHero.no + "编号英雄,不能修改");
}
public void del(int no){
HeroNode2 temp = head.next;
if (head.next == null){
System.out.println("链表为空~");
}
boolean flag = false;
while (true){
if (temp == null) {
break;
}
else if (temp.no == no){
flag = true;
break;
}
temp = temp.next;
}
if (flag){
temp.pre.next = temp.next;
if (temp.next != null) temp.next.pre = temp.pre;
}else System.out.println("没有对应下标英雄,无法删除");
}
}
class HeroNode2{
public int no;
public String name;
public String nickname;
public HeroNode2 next;
public HeroNode2 pre;
public HeroNode2(int no, String name, String nickname) {
this.no = no;
this.name = name;
this.nickname = nickname;
}
@Override
public String toString() {
return "HeroNode{" +
"no=" + no +
", name='" + name + '\'' +
", nickname='" + nickname + '\'' +
'}';
}
}
用不带头结点的循环链表来处理,先构成有n个节点单循环链表,由k节点从1开始计数,记到m对应节点删除,从被删除节点下一个节点从1开始计数,直到最后一个节点从链表删除
package com.fu.datastruct.queue;
public class Joseph {
public static void main(String[] args) {
CircleSingleLinkedList c = new CircleSingleLinkedList();
c.addBoy(5);
c.showBoy();
c.countBoy(1,2,5);
}
}
class CircleSingleLinkedList{
private Boy first = null;
public void addBoy(int nums){
if (nums < 2) {
System.out.println("nums的值不正确");
return;
}
Boy curBoy = null;//辅助变量
for (int i = 1; i <= nums ; i++) {
//根据编号创建小孩变量
Boy boy = new Boy(i);
if (i == 1){
first = boy;
first.setNext(first);//构成环
curBoy = first;
}else {
curBoy.setNext(boy);
boy.setNext(first);
curBoy = boy;
}
}
}
public void showBoy(){
if (first == null){
System.out.println("这是空链表,无法遍历");
return;
}
Boy curBoy = first;
while (true){
System.out.println("小孩编号:" + curBoy.getNo());
if (curBoy.getNext() == first){
break;
}
curBoy = curBoy.getNext();
}
}
/**
*
* @param startNo 表示从第几个小孩开始数数
* @param countNum 表示数几下
* @param nums 表示最初几个小孩在圈内
*/
public void countBoy(int startNo,int countNum,int nums){
if (first == null|| startNo < 1 || startNo > nums){
System.out.println("参数输入错误,请重新输出");
return;
}
Boy helper = first;
while (true){
if (helper.getNext() == first){//最后
break;
}
helper = helper.getNext();
}
for (int i = 0; i < startNo - 1; i++) {
first = first.getNext();
helper = helper.getNext();
}
while(true){
if (helper == first){//圈中只有一人
break;
}
else {
for (int i = 0; i < countNum - 1; i++) {
first = first.getNext();
helper = helper.getNext();
}
System.out.println("小孩" + first.getNo() + "出圈");
first = first.getNext();
helper.setNext(first);
}
}
System.out.println("最后留在圈中小孩编号" + first.getNo());
}
}
class Boy{
private int no;
private Boy next;
public Boy(int no) {
this.no = no;
}
public Boy(int no, Boy next) {
this.no = no;
}
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public Boy getNext() {
return next;
}
public void setNext(Boy next) {
this.next = next;
}
}
1. 栈的英文stack
2. 栈是**先入后出**有序列表
3. 栈是限制线性表中元素插入和删除只能在线性表一端进行的特殊线性表,允许插入和删除的一端为变化的一端,为变化的一端,称为**栈顶**,另一端为固定的一端,称为**栈底**
4. 根据栈的定义可知,最先放入栈的元素在栈底,最后放入元素在栈顶,删除元素则相反,最后放入元素最先删除,最先放入元素最后删除
package com.fu.datastruct.stack;
import com.sun.org.apache.bcel.internal.generic.IF_ACMPEQ;
import java.util.Scanner;
import java.util.Stack;
public class ArrayStackDemo {
public static void main(String[] args) {
ArrayStack stack = new ArrayStack(4);
boolean loop = true;
String key = "";
Scanner scanner = new Scanner(System.in);
while(loop){
System.out.println("push 入栈操作");
System.out.println("pop 出栈操作");
System.out.println("list 打印操作");
System.out.println("exit 离开操作");
System.out.println("请输入你的操作:");
key = scanner.next();
switch (key){
case "push":
System.out.println("请输入入栈的值:");
int value = scanner.nextInt();
stack.push(value);
break;
case "pop":
stack.pop();
break;
case "list":
stack.list();
break;
case "exit":
scanner.close();
loop = false;
break;
default:
break;
}
}
System.out.println("退出程序~~");
}
}
class ArrayStack{
private int[] stack;
private int maxSize;
private int top = -1;
//构造器
public ArrayStack(int maxSize) {
this.maxSize = maxSize;
stack = new int[this.maxSize];
}
//栈满
public boolean isFull(){
return top == maxSize - 1;
}
//栈空
public boolean isEmpty(){
return top == -1;
}
//入栈
public void push(int value){
if (isFull()){
System.out.println("栈满");
return;
}
top++;
stack[top] = value;
}
//出栈
public int pop() {
if (isEmpty()){
throw new RuntimeException("栈空");
}
int value = stack[top];
top--;
return value;
}
//遍历
public void list(){
if (isEmpty()){
throw new RuntimeException("栈空");
}
for (int i = top; i >= 0; i--) {
System.out.printf("stack[%d] = %d\n",i,stack[i]);
}
}
}
中缀表达式求值就是正常做法,对计算机并不友好,计算时常常把中缀转成后缀
正常表达式 | 逆波兰表达式 |
---|---|
a + b | a b + |
a + ( b - c) | a b c - + |
a + (b - c) * d | a b c - d * + |
a + d * (b - c) | a d b c - * + |
a = 1 + 3 | a 1 3 + = |
从左到右扫描表达式,遇到数字时,数字压入堆栈,遇到运算符,弹出栈顶两个数,用运算符对他们做相应的计算,将结果入栈:重复上述过程直到表达式最右端,最后得出表达式的结果
不要忘了* / 优先于 + -
package com.fu.datastruct.stack;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
public class PolandNotation {
public static void main(String[] args) {
String str = "3 4 + 5 * 6 -";
System.out.println(calculate(getListString(str)));
}
//数据运算符放入ArrayList
public static List<String> getListString(String str){
String[] split = str.split(" ");
List<String> list = new ArrayList<>();
for (String s : split) {
list.add(s);
}
return list;
}
//完成对逆波兰表达式计算
public static int calculate(List<String> ls) {
//创建一个栈,只需要一个栈即可
Stack<String> stack = new Stack<>();
for (String l : ls) {
if (l.matches("\\d+")){
stack.push(l);
}
else {
int num2 = Integer.parseInt(stack.pop());
int num1 = Integer.parseInt(stack.pop());
int res = 0;
if (l.equals("+")){
res = num1 + num2;
}
else if (l.equals("-")){
res = num1 - num2;
}
else if (l.equals("*")){
res = num1 * num2;
}
else if (l.equals("/")){
res = num1 / num2;
}
else {
throw new RuntimeException("输入错误!!!");
}
stack.push(res + "");
}
}
return Integer.parseInt(stack.pop());
}
}
后缀不好写出来,中缀好写
具体步骤:
package com.fu.datastruct.stack;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
public class PolandNotation {
public static void main(String[] args) {
String e = "1+((2+3)*4)-5";//[1, +, (, (, 2, +, 3, ), *, 4, ), -, 5]
List<String> infixExpressionList = toInfixExpressionList(e);
System.out.println("中缀表达式: "+infixExpressionList);
List<String> suffixExpressionList = parseSuffixExpressionList(infixExpressionList);
System.out.println("后缀表达式: "+suffixExpressionList);
System.out.println(calculate(suffixExpressionList));
}
public static List<String> parseSuffixExpressionList(List<String> ls){
Stack<String> s1 = new Stack<>();
List<String> s2 = new ArrayList<>();
for (String item : ls) {
if (item.matches("\\d+")){
s2.add(item);
}else if (item.equals("(")){
s1.push(item);
}else if (item.equals(")")){
while (!s1.peek().equals("(")){
s2.add(s1.pop());
}
s1.pop();
}else {
while (s1.size() != 0 && Operation.getValue(s1.peek()) >= Operation.getValue(item)){
s2.add(s1.pop());
}
s1.push(item);}
}
while (s1.size()!=0)s2.add(s1.pop());
return s2;
}
public static List<String> toInfixExpressionList(String s){
List<String> ls = new ArrayList<>();
int i = 0;
String s1;
char c ;
do {
if ((c = s.charAt(i))<48||(c = s.charAt(i))>57){
ls.add("" + c);
i++;
}
else {
s1 = "";
while (i < s.length() && (c=s.charAt(i))>=48 && (c=s.charAt(i))<=57){
s1 += c;
i++;
}
ls.add(s1);
}
} while(i < s.length());
return ls;
}
//完成对逆波兰表达式计算
public static int calculate(List<String> ls) {
//创建一个栈,只需要一个栈即可
Stack<String> stack = new Stack<>();
for (String l : ls) {
if (l.matches("\\d+")){
stack.push(l);
}
else {
int num2 = Integer.parseInt(stack.pop());
int num1 = Integer.parseInt(stack.pop());
int res = 0;
if (l.equals("+")){
res = num1 + num2;
}
else if (l.equals("-")){
res = num1 - num2;
}
else if (l.equals("*")){
res = num1 * num2;
}
else if (l.equals("/")){
res = num1 / num2;
}
else {
throw new RuntimeException("输入错误!!!");
}
stack.push(res + "");
}
}
return Integer.parseInt(stack.pop());
}
}
class Operation{
private static int ADD = 1;
private static int SUB = 1;
private static int MUL = 2;
private static int DIV = 2;
public static int getValue(String operation){
int result = 0;
switch (operation){
case "+":
result = ADD;
break;
case "-":
result = SUB;
break;
case "*":
result = MUL;
break;
case "/":
result = DIV;
break;
default:
System.out.println("不存在该运算符!!!");
break;
}
return result;
}
}
递归就是方法自己调用自己,每次调用时传入不同的变量,递归有助于编程者解决复杂的问题,可以让代码更加简洁
package com.fu.recursion;
public class MiGong {
public static void main(String[] args) {
int[][] map = new int[8][7];
for (int i = 0; i < 7; i++) {
map[0][i] = 1;
map[7][i] = 1;
}//上下为1
for (int i = 0; i < 8; i++) {
map[i][0] = 1;
map[i][6] = 1;
}//左右为1
map[3][1] = 1;
map[3][2] = 1;//挡板为1
System.out.println("地图情况:");
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 7; j++) {
System.out.print(map[i][j] + " ");
}
System.out.println();
}
setWay(map,1,1);
System.out.println("小球走过的地图情况:");
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 7; j++) {
System.out.print(map[i][j] + " ");
}
System.out.println();
}
}
/**
*
* @param map 表示地图
* @param i 从哪个位置开始找
* @param j
* @return 如果找到通路,就返回true,否则返回false
* 小球到达map[6][5]就说明通路找到了
* map[i][j]=0表示该点没有走过,1表示墙,2表示可以走,3表示该位置已经走过但是走不通
* 走迷宫时要确定一个策略,下 -> 右 -> 上 -> 左,如果该点走不通,再回溯
*
*
*/
public static boolean setWay(int[][]map,int i,int j){
if(map[6][5] == 2){
return true;
}else {
if (map[i][j] == 0){
map[i][j] = 2;
if (setWay(map,i+1,j)){
return true;
}else if (setWay(map,i,j+1)){
return true;
}else if (setWay(map,i-1,j)){
return true;
}else if (setWay(map,i,j-1)){
return true;
}else {
map[i][j] = 3;
return false;
}
}
else {//map[i][j] != 0 //1 2 3
return false;
}
}
}
}
指将需要处理的所有数据都加载到内部存储器(内存)中进行排序
数据量大,无法全部加载到内存中,需要借助外部存储进行排序
直接插入排序
希尔排序
简单选择排序
堆排序
冒泡排序
快速排序
归并排序
基数排序
可行
但对设计算法运行性能进行评测,需要实际运行该程序
所得时间统计量依赖计算机硬件、软件等环境因素
这种方式要在同一台计算机相同状态运行,才能比较哪个算法速度更快
通过分析某个方法时间复杂度来判断哪个算法更优
忽略常数项,忽略低次项,忽略系数
一个算法花费时间与语句执行次数成正比,哪个算法语句执行次数多,花费时间多,一个算法语句执行次数称为语句频度或时间频度
用常数1代替运行时间中所有加法常数
修改后运行次数函数中,只保留最高阶项
去除最高阶项系数
常见时间复杂度
常见时间复杂度从小到大排序:O(1) 我们应该避免使用指数阶算法 平均时间复杂度指所有可能的输入实例均以等概率出现情况下,该算法运行时间 最坏情况时间复杂度称最坏时间复杂度,一般讨论时间复杂度均是最坏复杂度 理由:最坏情况下时间复杂度是算法在任何输入实例上运行时间界限,就保证了算法运行时间不会比最坏情况更长 排序过程元素不断接近自己位置,一趟比较没有进行交换,说明序列有序,要在排序中设置flag判断元素是否进行过交换,减少不必要的比较 原始的数组:101,34,119,1 说明: 插入式排序属于内部排序法,是对于欲排序的元素以插入的方式找寻该元素的 插入排序(Insertion Sorting)的基本思想是:把n个待排序的元素看成为 希尔排序是希尔(Donald Shell)于1959年提出的一种排序算法。希尔排序也是 希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序; [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ytF671hd-1643456651036)(C:\Users\11021\AppData\Roaming\Typora\typora-user-images\1643267909953.png)] 最简单的查找,思路就是从头到尾查找 思路: 黄金分割点值把一条线段分割两部分,一部分与全长之比等于另一部分与这部分之比 取其前三位数字近似值0.618,由于按此比例设计的造型十分美丽,因此成为黄金分割,称为中外比,一个神奇的数字,带来意想不到效果 斐波拉契数列{1,1,2,3,5,8,13,21,34,55}发现斐波那契数列两个相邻数比例无限接近黄金分割值0.168 散列表又叫哈希表,是根据关键码值直接进行访问数据结构,也就是说,通过关键码映射到表中的一个位置来访问记录,加快查找速度,这个映射函数叫散列函数,存放记录数组是散列表 哈希表结构: 数组 + 链表 数组 + 二叉树 散列表根据关键码值直接进行访问的数据结构,就是说,通过把关键码值映射到表中的一个位置来访问记录,加快查找的速度,这个映射函数叫散列函数,存放记录的数组叫散列表 数组的插入删除效率低 链表的查找效率低 数保证了各项的速度 创建一颗二叉树 先输出父节点,再遍历左子树和右子树 如果左子节点不为空,则递归继续前序遍历 如果右子节点不为空,则递归继续前序遍历 先遍历左子树,再输出父节点,再遍历右子树 如果当前节点的左子节点不为空,递归中序遍历 输出当前节点 如果当前节点的右子节点不为空,递归中序遍历 先遍历左子树和右子树,再输出父节点 看输出父节点的顺序,确定前序和后序 如果当前节点的左子节点不为空,递归后序遍历 如果当前节点的右子节点不为空,递归中序遍历 输出当前节点 如果树是空树root,只有一个root节点,等价将二叉树置空 、我们二叉树单向的,所以我们判断当前节点的子节点是否需要删除节点,不能去判断这个节点是不是需要删除节点 如果当前节点的左子节点不为空,并且左子节点就是要删除的节点,将this.left = null,并且返回(结束递归删除) 如果当前节点右子节点不为空,并且右子节点就是要删除的节点,this.right = null,并且返回(结束递归删除) 第二步和第三步没有删除节点,我们就需要向左子树进行递归删除 第四步没有删除节点,应当行啊右子树进行递归删除 != null){ }
算法空间复杂度
冒泡排序
规则
package com.fu.sort;
import java.util.Arrays;
public class BubbleSort {
public static void main(String[] args) {
int a[] = {9,2,10,7,5,6,4,8,1,3};
int temp;
boolean flag = false;
for (int i = 0; i < a.length-1; i++) {
for (int j = 0; j < a.length-1-i; j++) {
if (a[j]>a[j+1]){
flag = true;
temp = a[j];
a[j] = a[j+1];
a[j+1] = temp;
}
}
if (!flag)break;
else flag = false;
System.out.println(Arrays.toString(a));
}
}
}
选择排序
第一轮排序:
1,34,119,101
第二轮排序:
1,34,119,101
第三轮排序:
1,34,101,119
1.选择排序一共有数组大小-1轮排序
2.每1轮排序,又是一个循环,循环的规则(代码)
2.1先假定当前这个数是最小数
2.2 然后和后面的每个数进行比较,如果发现有比当前数更小的数,
就重新确定最小数,并得到下标
2.3 当遍历到数组的最后时,就得到本轮最小数和下标
2.4 交换[代码]package com.fu.sort;
import java.util.Arrays;
public class SelectSort {
public static void main(String[] args) {
int a[] = {101,34,119,1};
System.out.println(Arrays.toString(a));
selectSort(a);
System.out.println(Arrays.toString(a));
}
public static void selectSort(int[] arr){
for (int i = 0; i < arr.length - 1; i++) {
int minIndex = i;
int min = arr[i];
for (int j = i + 1; j < arr.length; j++) {
if (min > arr[j]){
min = arr[j];
minIndex = j;
}
}
if (minIndex != i){
arr[minIndex] = arr[i];
arr[i] = min;
}
}
}
}
插入排序
适当位置,以达到排序的目的。思想:
一个有序表和一个无序表,开始时有序表中只包含一个元素,无序表中
包含有n-1个元素,排序过程中每次从无序表中取出第一个元素,把它
的排序码依次与有序表元素的排序码进行比较,将它插入到有序表中的
适当位置,使之成为新的有序表。package com.fu.sort;
import java.util.Arrays;
public class InsertSort {
public static void main(String[] args) {
int []arr = {101,29,232,1};
insertSort(arr);
System.out.println(Arrays.toString(arr));
}
public static void insertSort(int []arr){
for (int i = 0; i < arr.length-1; i++) {
int insertVal = arr[i+1];
int insertIndex = i;
while (insertIndex >= 0 && insertVal < arr[insertIndex]){
arr[insertIndex + 1] = arr[insertIndex];
insertIndex--;
}
arr[insertIndex + 1] = insertVal;
}
}
}
希尔排序
希尔排序法介绍
一种插入排序,它是简单插入排序经过改进之后的一个更高效的版本,也称为
缩小增量排序。希尔排序法基本思想
随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰
被分成一组,算法便终止package com.fu.sort;
import java.util.Arrays;
/**
* 希尔排序移动法(优化)
*/
public class ShellSort {
public static void main(String[] args) {
int []arr = {8,9,1,7,2,3,5,4,6,0};
shellSort(arr);
}
public static void shellSort(int []arr){
for (int gap = arr.length/2; gap > 0; gap/=2) {
for (int i = gap; i < arr.length; i++) {
int j = i;
int temp = arr[j];
if (arr[j] < arr[j-gap]){
while(j - gap >= 0 && temp < arr[j - gap]){
arr[j] = arr[j-gap];
j -= gap;
}
arr[j] = temp;
}
}
System.out.println(Arrays.toString(arr));
}
}
}
快速排序
快速排序(Quicksort)是对冒泡排序的一种改进。基本思想是:通过一趟排序
将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分
的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个
排序过程可以递归进行,以此达到整个数据变成有序序列
package com.fu.sort;
import java.util.Arrays;
public class QuickSort {
public static void main(String[] args) {
int []arr = {-9,78,0,23,-567,70};
quickSort(arr,0,arr.length-1);
System.out.println(Arrays.toString(arr));
}
/**
*
* @param arr 传入数组
* @param left 左下标
* @param right 右下标
*/
public static void quickSort(int []arr,int left,int right){
int l = left;
int r = right;
int pivot = arr[(left + right)/2];
int temp = 0;
//循环让比pivot值小的放左边,大的放右边
while (l < r){
//pivot左边找到大于等于pivot的值
while (arr[l]<pivot){
l += 1;
}
//pivot右边找到小于等于pivot的值
while (arr[r]>pivot){
r -= 1;
}
if (l >= r){
break;
}
//交换
temp = arr[l];
arr[l] = arr[r];
arr[r] = temp;
//交换完,arr[l] == pivot值,相等--,前移
if (arr[l] == pivot){
r -= 1;
}
//交换完,arr[r] == pivot值,相等++,后移
if (arr[r] == pivot){
l += 1;
}
}
if (l == r){
l += 1;
r -= 1;
}
if (left < r){
quickSort(arr,left,r);
}
if (right > l){
quickSort(arr,l,right);
}
}
}
归并排序
归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典
的分治(divide-and-conquer)策略(分治法将问题分(divide)成一些小的问
题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修补"在
起,即分而治之)。
package com.fu.sort;
import java.util.Arrays;
public class MergerSort {
public static void main(String[] args) {
int arr[] = {8,4,5,7,1,3,6,2};
int temp[] = new int[arr.length];
mergeSort(arr,0 ,arr.length-1,temp);
System.out.println(Arrays.toString(arr));
}
public static void mergeSort(int []arr,int left,int right,int[]temp ){
if (left < right){
int mid = (left + right)/2;
mergeSort(arr,left,mid,temp);
mergeSort(arr,mid+1,right,temp);
merge(arr,left,mid,right,temp);
}
}
/**
*
* @param arr 排序的原始数组
* @param left 左边有序序列初始序列
* @param mid 中间索引
* @param right 右边索引
* @param temp 做中转的数组
*/
public static void merge(int []arr ,int left ,int mid ,int right ,int []temp){
int i = left;
int j = mid + 1;
int t = 0;
while (i <= mid && j<=right){
if (arr[i]<=arr[j]){
temp[t] = arr[i];
t+=1;
i+=1;
}else {
temp[t] = arr[j];
t+=1;
j+=1;
}
}
while(i <= mid){
temp[t] = arr[i];
t+=1;
i+=1;
}
while(j <= right){
temp[t] = arr[j];
t+=1;
j+=1;
}
//拷贝temp数组
t = 0;
int templeft = left;
while(templeft <= right){
arr[templeft] = temp[t];
t+=1;
templeft+=1;
}
}
}
基数排序(桶排序)
介绍
基本思想
package com.fu.sort;
import java.util.Arrays;
public class RadixSort {
public static void main(String[] args) {
int arr[] = {53, 3, 542, 748, 14, 214};
radixSort(arr);
}
public static void radixSort(int[] arr) {
int max = arr[0];
for (int i = 0; i < arr.length; i++) {
if (arr[i]>max){
max = arr[i];
}
}
int maxLength = (max + "").length();
int[][] bucket = new int[10][arr.length];
int[] bucketElementCounts = new int[10];
for (int i = 0,n=1; i < maxLength; i++,n*=10) {
for (int j = 0; j < arr.length; j++) {
int digitOfElement = arr[j] /n % 10;
bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j];
bucketElementCounts[digitOfElement]++;
}
int index = 0;
for (int k = 0; k < bucketElementCounts.length; k++) {
if (bucketElementCounts[k] != 0){
for (int l = 0; l < bucketElementCounts[k]; l++) {
arr[index++] = bucket[k][l];
}
}
bucketElementCounts[k] = 0;
}
System.out.println(Arrays.toString(arr));
}
}
}
常见排序算法比较和总结
查找
java中常用查找:
顺序(线性)查找
package com.fu.search;
public class SeqSearch {
public static void main(String[] args) {
int arr[] = {1,9,11,-1,34,89};
int index = seqSearch(arr,11);
if (index == -1){
System.out.println("没有找到");
}else {
System.out.println("找到,下标:"+ index);
}
}
/**
*
* @param arr
* @param value
* @return
*/
public static int seqSearch(int []arr,int value){
for (int i = 0; i < arr.length; i++) {
if (arr[i] == value){
return i;
}
}
return -1;
}
}
二分查找
1. 首先确定数组中间下标
2. 然后让需要查找的数比较
3. 要查找的数在mid左边,递归的向右查找
4. 要查找的数在mid右边,递归的向左查找
5. 找到即返回,结束递归
6. 递归完整个数组,仍然没有找到,也要结束递归
package com.fu.search;
//二分查找数组必须有序
public class BinarySearch {
public static void main(String[] args) {
int arr[] = {1, 8, 10, 89, 1000, 1234};
System.out.println(binarySearch(arr, 0, arr.length - 1, 88));
}
/**
*
* @param arr 数组
* @param left 左边索引
* @param right 右边索引
* @param findVal 要查找的值
* @return 找到返回下标,找不到返回-1
*/
public static int binarySearch(int []arr,int left,int right,int findVal){
int mid = (left + right)/2;
int midVal = arr[mid];
if (left> right){return -1;}
if (findVal > midVal){
return binarySearch(arr,mid + 1,right,findVal);
}
else if (findVal < midVal){
return binarySearch(arr,left,mid-1,findVal);
}else {
return mid;
}
}
}
插值查找
package com.fu.search;
import java.util.Arrays;
public class InsertSearch {
public static void main(String[] args) {
int []arr = new int[100];
for (int i = 0; i < 100; i++) {
arr[i] = i+1;
}
System.out.println(insertValueSearch(arr, 0, arr.length-1, 9));
}
/**
* 插值查找要求数组有序
* @param arr 数组
* @param left 左边索引
* @param right 右边索引
* @param findVal 查找值
* @return
*/
public static int insertValueSearch(int []arr,int left,int right,int findVal){
if(left > right || findVal < arr[0] || findVal > arr[arr.length-1]){
return -1;
}
int mid = left + (right - left) * (findVal - arr[left])/(arr[right] - arr[left]);
int midVal = arr[mid];
if (findVal > midVal){//说明应该向右边递归
return insertValueSearch(arr,mid+1,right,findVal);
} else if (findVal<midVal){//说明应该向左边递归
return insertValueSearch(arr,left,mid-1,findVal);
} else {
return mid;
}
}
}
斐波拉契查找 0.168
package com.fu.search;
import java.util.Arrays;
public class FibonacciSearch {
public static int maxSize = 20;
public static void main(String[] args) {
int []arr = {1,8,10,89,1000,1234};
System.out.println(fibSearch(arr,1));
}
//得到一个斐波拉契数列
public static int[] fib(){
int []f = new int [maxSize];
f[0] = 1;
f[1] = 1;
for (int i = 2; i < maxSize; i++) {
f[i] = f[i-1] + f[i-2];
}
return f;
}
/**
*
* @param a 数组
* @param key 需要的关键码
* @return 返回对应下标/-1
*/
public static int fibSearch(int [] a,int key){
int low = 0;
int high = a.length - 1;
int k = 0;
int mid = 0;
int f[] = fib();//获取斐波拉契数列
//获取斐波拉契数列下标
while (high > f[k]-1){
k++;
}
int []temp = Arrays.copyOf(a,f[k]);
for (int i = high+1; i < temp.length; i++) {
temp[i] = a[high];
}
while(low <= high){
mid = low + f[k-1] -1;
if (key < temp[mid]){
high = mid - 1;
k--;
}
else if (key > temp[mid]){
low = mid + 1;
k -= 2;
}else {
if (mid <= high){
return mid;
}else {
return high;
}
}
}return -1;
}
}
哈希表
基本介绍
package com.fu.hashtab;
import java.util.Scanner;
public class HashTabDemo {
public static void main(String[] args) {
HashTab hashTab = new HashTab(10);
String key = "";
Scanner scanner = new Scanner(System.in);
while(true) {
System.out.println("add 添加雇员");
System.out.println("list 显示雇员");
System.out.println("find 查找雇员");
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 "find":
System.out.println("输入要查找的id");
id = scanner.nextInt();
hashTab.findEmpById(id);
break;
case "exit":
scanner.close();
System.exit(0);
default:
break;
}
}
}
}
class Emp{
public int id;
public String name;
public Emp next;//默认为空
public Emp(int id, String name) {
this.id = id;
this.name = name;
}
}
class HashTab{
private EmpLinkedList[] empLinkedListArray;
private int size;
public HashTab(int size) {
this.size = size;
empLinkedListArray = new EmpLinkedList[size];
//初始化每一条链表
for (int i = 0; i < size; i++) {
empLinkedListArray[i] = new EmpLinkedList();
}
}
public void add(Emp emp){
int empLinkedListNO = hashFun(emp.id);
empLinkedListArray[empLinkedListNO].add(emp);
}
public int hashFun(int id){
return id % size;
}
public void list(){//遍历hash表
for (int i = 0; i < size; i++) {
empLinkedListArray[i].list(i);
}
}
public void findEmpById(int id){
int empLinkedListNO = hashFun(id);
Emp emp = empLinkedListArray[empLinkedListNO].findEmpById(id);
if (emp != null){
System.out.printf("在%d条链表中找到雇员id = %d\n",(empLinkedListNO + 1),id);
}else{
System.out.println("在哈希表中没有找到该雇员");
}
}
}
class EmpLinkedList{
private Emp head;
//添加
public void add(Emp emp){
if (head == null){
head = emp;
return;
}
Emp curEmp = head;
while (true){
if (curEmp.next == null){
break;
}
curEmp = curEmp.next;
}
curEmp.next = emp;
}
//遍历
public void list(int no){
if (head == null){
System.out.println("第"+(no+1)+"当前链表为空");
return;
}
System.out.println("第"+(no+1)+"条链表信息为:");
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();
}
public Emp findEmpById(int id){
if (head == null){
System.out.println("链表为空");
}
Emp curEmp = head ;
while (true){
if (curEmp.id == id){
break;
}
if (curEmp.next == null){
curEmp = null;
}
curEmp = curEmp.next;
}
return curEmp;
}
}
树
树 vs 数组 vs 链表
二叉树
树的遍历
前序遍历:
中序遍历:
后序遍历:
树的常用术语:
package com.fu.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.setLeft(node2);
root.setRight(node3);
node3.setRight(node4);
System.out.println("前序遍历");
binaryTree.setRoot(root);
binaryTree.preOrder();
System.out.println("后序遍历");
binaryTree.infixOrder();
System.out.println("中序遍历");
binaryTree.postOrder();
}
}
class BinaryTree{
private HeroNode root;
public void setRoot(HeroNode root) {
this.root = 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("二叉树为空,无法遍历");
}
}
}
class HeroNode{
private int no;
private String name;
private HeroNode left;
private HeroNode right;
public HeroNode(int no, String name) {
this.no = no;
this.name = name;
}
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public HeroNode getLeft() {
return left;
}
public void setLeft(HeroNode left) {
this.left = left;
}
public HeroNode getRight() {
return right;
}
public void setRight(HeroNode right) {
this.right = right;
}
@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);
}
}
二叉树查找
前序查找思路:
中序查找思路
后序查找思路
package com.fu.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.setLeft(node2);
root.setRight(node3);
node3.setRight(node4);
System.out.println("前序遍历");
binaryTree.setRoot(root);
binaryTree.preOrder();
System.out.println("后序遍历");
binaryTree.infixOrder();
System.out.println("中序遍历");
binaryTree.postOrder();
HeroNode resNode = binaryTree.preOrderSearch(4);
if (resNode != null){
System.out.printf("找到了,信息no=%d name=%s",resNode.getNo(),resNode.getName());
}else {
System.out.printf("没有找到no = %d的英雄",5);
}
}
}
class BinaryTree{
private HeroNode root;
public void setRoot(HeroNode root) {
this.root = 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("二叉树为空,无法遍历");
}
}
//前序查找
public HeroNode preOrderSearch(int no){
if (root != null){
return root.postOrderSearch(no);
}else {
return null;
}
}
//中序查找
public HeroNode infixOrderSearch(int no){
if (root != null){
return root.preOrderSearch(no);
}else {
return null;
}
}
//后序遍历
public HeroNode postOrderSearch(int no) {
if (root != null) {
return root.postOrderSearch(no);
}else {
return null;
}
}
}
class HeroNode{
private int no;
private String name;
private HeroNode left;
private HeroNode right;
public HeroNode(int no, String name) {
this.no = no;
this.name = name;
}
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public HeroNode getLeft() {
return left;
}
public void setLeft(HeroNode left) {
this.left = left;
}
public HeroNode getRight() {
return right;
}
public void setRight(HeroNode right) {
this.right = right;
}
@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);
}
//前序查找
/**
*
* @param no 查找no
* @return 找到返回Node,没找到返回null
*/
public HeroNode preOrderSearch(int no){
if (this.no == 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);
}
if (resNode != null){
return resNode;
}
if (this.no == no){
return this;
}
return resNode;
}
}
二叉树删除节点
思路:
package com.fu.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.setLeft(node2);
root.setRight(node3);
node3.setRight(node4);
System.out.println("前序遍历");
binaryTree.setRoot(root);
binaryTree.preOrder();
System.out.println("后序遍历");
binaryTree.infixOrder();
System.out.println("中序遍历");
binaryTree.postOrder();
HeroNode resNode = binaryTree.preOrderSearch(4);
if (resNode != null){
System.out.printf("找到了,信息no=%d name=%s",resNode.getNo(),resNode.getName());
}else {
System.out.printf("没有找到no = %d的英雄",5);
}
System.out.println("删除前,前序遍历~~~");
binaryTree.preOrder();
binaryTree.delNode(5);
System.out.println("删除后,前序遍历~~~");
binaryTree.preOrder();
}
}
class BinaryTree{
private HeroNode root;
public void setRoot(HeroNode root) {
this.root = root;
}
//删除节点
public void delNode(int no){
if (root != null){
if (root.getNo() == no){
root = null;
}else {
root.delNode(no);
}
}else {
System.out.println("空数不能删除");
}
}
//前序遍历
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("二叉树为空,无法遍历");
}
}
//前序查找
public HeroNode preOrderSearch(int no){
if (root != null){
return root.postOrderSearch(no);
}else {
return null;
}
}
//中序查找
public HeroNode infixOrderSearch(int no){
if (root != null){
return root.preOrderSearch(no);
}else {
return null;
}
}
//后序遍历
public HeroNode postOrderSearch(int no) {
if (root != null) {
return root.postOrderSearch(no);
}else {
return null;
}
}
}
class HeroNode{
private int no;
private String name;
private HeroNode left;
private HeroNode right;
public HeroNode(int no, String name) {
this.no = no;
this.name = name;
}
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public HeroNode getLeft() {
return left;
}
public void setLeft(HeroNode left) {
this.left = left;
}
public HeroNode getRight() {
return right;
}
public void setRight(HeroNode right) {
this.right = right;
}
@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);
}
}
//前序遍历
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);
}
//前序查找
/**
*
* @param no 查找no
* @return 找到返回Node,没找到返回null
*/
public HeroNode preOrderSearch(int no){
if (this.no == 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);
}
if (resNode != null){
return resNode;
}
if (this.no == no){
return this;
}
return resNode;
}
}
this.left.delNode(no);
}
if (this.right != null){
this.right.delNode(no);
} }
//前序遍历
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);
}
//前序查找
/**
*
* @param no 查找no
* @return 找到返回Node,没找到返回null
*/
public HeroNode preOrderSearch(int no){
if (this.no == 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);
}
if (resNode != null){
return resNode;
}
if (this.no == no){
return this;
}
return resNode;
}