java基础-11 : 数据结构与算法
一.数据结构
数据结构可视化网站
1.栈
先进后出,后进先出
2.队列
先进先出,后进后出
3.链表
查询慢,增删快
4.数组
查询快,增删慢
5.树
1.二叉树
弊端:数据在存入时没有规则,查找二叉树时只能通过遍历整个树进行查找
1.二叉树的遍历方式
- 前序遍历:当前节点,左子节点,右子节点
- 中序遍历:左子节点,当前节点,右子节点
- 后续遍历:左子节点,右子节点,当前节点
- 层序遍历:一层一层的从左往右遍历
2.查找二叉树
比当前节点大的放在右子节点中,比当前节点小的放在左子节点中
弊端:可能会出现一个子树树高很高,另一个字数树高为0的的情况
3.平衡二叉树
原因:第一棵树中''10''这个节点左子树高度0,右子树高度3,相差超过1,所以不是平衡二叉树
1.左旋
当添加一个新的数据"12"时,整个树就由平衡→不平衡了
确定支点:从添加的节点开始,不断的往父节点找不平衡的点
- 以不平衡的点作为支点("10")
- 把支点降为左子节点,
- 晋升原来的右子节点
1.1练习
当添加数据"12"后,
- 以不平衡的点为支点("7")
- 将支点降为左子节点
- 晋升原来的右子节点
- 将多余的左子节点给已经降级的根节点当右子节点
2.右旋
当添加一个新的数据"1"时,整个树就由平衡→不平衡了
确定支点:从添加的节点开始,不断的往父节点找不平衡的点
- 以不平衡的点作为支点("4")
- 把支点降为右子节点,
- 晋升原来的左子节点
2.1练习
当添加数据"1"时
- 以不平衡的点为支点("7")
- 将支点降为右子节点
- 晋升原来的左子节点
- 将多余的右子节点给已经降级的根节点当左子节点
4.练习
1.当在跟节点的左字数的右子树添加数字"6"时,不平衡的点为"7"
2.如果将其进行右旋,变为:
3.发现依然是不平衡二叉树,不平衡的点为"4",所以将原来的左子树进行局部的左旋,变为:
4.然后再进行右旋即可:
5.红黑树
红黑规则:
- 每一个节点都是红色或黑色的
- 根节点必须为黑色
- 如果节点没有子节点或父节点,则该节点相应地指针属性为nil,这些nil视为叶节点,每个叶节点(nil)是黑色的
- 如果某一个节点是红色的,则它的子节点必须为黑色(既不能出现红红相连的情况)
- 对每一个节点,从该节点到其所有后代叶节点(nil)的简单路径(只能往前,不能回头)上,均包含相同数目的黑色节点
红黑树在添加节点时,默认为红色(提高效率)
1.练习
现有一颗红黑树,需要添加"22","17","24","19",这几个数据
1.添加数据"22"时,发现违背了红红相连的规则,则需要进行调整颜色,因为数据"22"的父节点"23"为红,叔叔节点"18"也为红,根据规则进行变换
2.添加数据"17","19","22","24"后,没有违背规则
3.添加数据"15"后,出现了红红相连的情况,则根据规则进行判断,然后再判断数据"18"
4.添加数据"14"后,出现红红相连的违规情况,
6.B-Tree
7.B+树
二.查找
1.基本查找
从第一个元素开始遍历数组,将遍历的数据与目标数据进行比较
public class 基本查找 {public static void main(String[] args){int[] arr = {1,3,4,5,7,8,9,11,22,34,57,89,100};int target = 22;int index = basicFind(arr,target);System.out.println(index);}public static int basicFind(int[] arr,int target) {for (int i = 0; i < arr.length; i++) {if (arr[i] == target) {return i;}}return -1;}
}
2.二分查找
将取数组的左右索引的中间值,将中间值的数据与目标数据进行比较
- 目标数据大于中间值,则左索引变为中间值+1
- 目标数据小于中间值,则右索引变为中间值-1
public class 二分查找 {public static void main(String[] args){int[] arr = {1,3,4,5,7,8,9,11,22,34,57,89,100};int target = 22;int index = midFind(arr,target);System.out.println(index);}public static int midFind(int[] arr,int target) {int min = 0;int max = arr.length-1;while (min <= max) {int mid = (min + max) / 2;if (arr[mid] == target) {return mid;} else if (arr[mid] > target) {max = mid - 1;} else if (arr[mid] < target) {min = mid + 1;}}return -1;}
}
3.插值查找
数据只有在均匀分布时才会有作用
中间值为:左索引+目标值与左索引数值差 * (左右索引差 / 左右索引数值差)
public class 插值查找 {public static void main(String[] args){int[] arr = {2,4,6,8,10,12,14,16,18,20};int target = 14;int index = findIndex(arr,target);System.out.println(index);}public static int findIndex(int[] arr,int target) {int left = 0;int right = arr.length-1;while (left <= right) {int mid = left + (right - left) * (target - arr[left]) / (arr[right] - arr[left]);if (arr[mid] == target) {return mid;} else if (arr[mid] > target) {right = mid - 1;} else if (arr[mid] < target) {left = mid + 1;}}return -1;}
}
4.分块查找
1.分块查找1
定义一个块类,包含最大值,起始索引,结束索引
public class 分块查找 {public static void main(String[] args) {Block[] block = new Block[4];block[0] = new Block(10, 0, 1);block[1] = new Block(20, 2, 5);block[2] = new Block(40, 6, 10);block[3] = new Block(50, 11, 13);int[] arr = {7, 10,19, 16, 20, 13,27, 22, 30, 40, 36,43, 50, 48};int target = 22;int index = blockFind(arr,block, target);System.out.println(index);}public static int blockFind(int[] arr,Block[] block,int target) {int blockIndex = blockIndex(block, target);if (blockIndex == -1) {return -1;}int startIndex = block[blockIndex].getStartIndex();int endIndex = block[blockIndex].getEndIndex();for (int i = startIndex; i <= endIndex; i++) {if (arr[i] == target) {return i;}}return -1;}public static int blockIndex(Block[] block, int target) {
// '21,'29'30,40'int left = 0;int right = block.length - 1;int ans = 0;while (block[ans].getMax() < target) {int mid = (left+right) / 2;if (block[mid].getMax() >= target) {ans = mid;right = mid - 1;} else {left = mid + 1;}}return ans;}
}
class Block {private int max;private int startIndex;private int endIndex;public Block() {}public Block(int max, int startIndex, int endIndex) {this.max = max;this.startIndex = startIndex;this.endIndex = endIndex;}public int getMax() {return max;}public void setMax(int max) {this.max = max;}public int getStartIndex() {return startIndex;}public void setStartIndex(int startIndex) {this.startIndex = startIndex;}public int getEndIndex() {return endIndex;}public void setEndIndex(int endIndex) {this.endIndex = endIndex;}
}
2.分块查找2
定义一个块类,包含最大值,最小值,起始索引,结束索引
public class 分块查找 {public static void main(String[] args) {int[] arr = {27,22,30,40,36,//22-4013,19,16,20,7,10,//7-2043,50,58};//43-58Block[] block = new Block[3];block[0] = new Block(40,22,0,4);block[1] = new Block(20,7,5,10);block[2] = new Block(58,43,11,13);int index = blockSearch(arr,block,20);if(index == -1){System.out.println("未找到");}}public static int blockSearch(int[] arr,Block[] block,int number){for (int i = 0; i < block.length; i++) {if(number >= block[i].min && number <= block[i].max){for (int j = block[i].startindex; j <= block[i].endindex; j++) {if(arr[j] == number){System.out.println("找到"+number+",下标为"+j);return j;}}}}return -1;}
}
class Block{int max;int min;int startindex;int endindex;public Block() {}public Block(int max, int min, int startindex, int endindex) {this.max = max;this.min = min;this.startindex = startindex;this.endindex = endindex;}public int getMax() {return max;}public void setMax(int max) {this.max = max;}public int getMin() {return min;}public void setMin(int min) {this.min = min;}public int getStartindex() {return startindex;}public void setStartindex(int startindex) {this.startindex = startindex;}public int getEndindex() {return endindex;}public void setEndindex(int endindex) {this.endindex = endindex;}
}
三.排序
1.冒泡排序
取出每一个数据,将其与每一个数据进行比较
public class 冒泡排序 {public static void main(String[] args) {int[] arr = {2, 1, 3, 7, 6, 5, 9, 3};for (int i = 0; i < arr.length-1; i++) {for (int j = 0; j < arr.length-1-i; j++) {if (arr[j] > arr[j+1]) {int temp = arr[j];arr[j] = arr[j+1];arr[j+1] = temp;}}System.out.print("第"+(i+1)+"轮排序结果:" );printArr(arr);}}public static void printArr(int[] arr) {for (int i = 0; i < arr.length; i++) {System.out.print(arr[i] + " ");}System.out.println();}
}
2.选择排序
public class 冒泡排序 {public static void main(String[] args) {int[] arr = {2, 1, 3, 7, 6, 5, 9, 3};for (int i = 0; i < arr.length-1; i++) {for (int j = i+1; j < arr.length; j++) {if (arr[i] > arr[j]) {int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}}System.out.print("第"+(i+1)+"轮排序结果:" );printArr(arr);}}public static void printArr(int[] arr) {for (int i = 0; i < arr.length; i++) {System.out.print(arr[i] + " ");}System.out.println();}
}
3.插入排序
public class 插入排序 {public static void main(String[] args) {int[] arr = {2, 3, 5, 6, 2, 4, 2, 3, 4, 5, 43, 2, 3, 4, 51, 34};int startindex = 0;for (int i = 0; i < arr.length; i++) {if (arr[i] < arr[i + 1]) {startindex = i + 2;} else {break;} ;}System.out.println(startindex);for (int i = startindex; i < arr.length; i++) {int j = i;while (j > 0 && arr[j] < arr[j - 1]) {int temp = arr[j];arr[j] = arr[j - 1];arr[j - 1] = temp;j--;}}for (int i = 0; i < arr.length; i++) {System.out.print(arr[i] + " ");}}
}
4.快速算法
public class 快速排序 {public static void main(String[] args) {int[] arr = {2, 1, 3, 7, 6, 5, 9, 3};quickSort(arr, 0, arr.length - 1);printArr(arr);System.out.println("快速排序完成");}public static void quickSort(int[] arr, int left, int right) {int pivot = arr[left];while (left != right) {while (true){if(arr[right] < pivot||right<=left){break;}right--;}while(true){if(arr[left] > pivot||left<=right){break;}left++;}}int temp = arr[left];arr[left] = arr[right];arr[right] = temp;quickSort(arr,left,-1);quickSort(arr,right+1,);}public static void printArr(int[] arr) {for (int i = 0; i < arr.length; i++) {System.out.print(arr[i] + " ");}}
}