网站建设哈尔滨网站建设1,wordpress插件买免费,wordpress ueditor 教程,1g做网站空间文章目录 第一部分#xff1a;查找算法二分查找插值查找分块查找哈希查找树表查找 第二部分#xff1a;排序算法冒泡排序选择排序插入排序快速排序 总结 第一部分#xff1a;查找算法
二分查找
也叫做折半查找#xff0c;属于有序查找算法。 前提条件#xff1a;数组数据… 文章目录 第一部分查找算法二分查找插值查找分块查找哈希查找树表查找 第二部分排序算法冒泡排序选择排序插入排序快速排序 总结 第一部分查找算法
二分查找
也叫做折半查找属于有序查找算法。 前提条件数组数据必须有序从小到大或者从大到小都是可以的。 如果是无序的也可以先进行排序。 但是排序之后会改变原有数据的顺序查找出来元素位置跟原来的元素可能是不一样的所以排序之后再查找只能判断当前数据是否在容器当中返回的索引无实际的意义。 基本思想用给定值先与中间结点比较。
比较完之后有三种情况
相等 说明找到了要查找的数据比中间节点小 说明要查找的数字在中间节点左边要查找的数据比中间节点大 说明要查找的数字在中间节点右边
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 - 1max 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;}}}插值查找
插值是在二分查找的基础上让中间的mid点尽可能靠近想要查找的元素。 修改mid公式即可
private static int binarySearch2(int[] arr, int num) {int min 0;int max arr.length - 1;while (true) {if (min max) {return -1;}int mid min (num - arr[min]) / (arr[max] - arr[min]) * (max - min);//这里改公式if (num arr[mid]) {min mid 1;} else if (num arr[mid]) {max mid - 1;} else {return mid;}}
}细节 对于表长较大而关键字分布又比较均匀的查找表来说插值查找算法的平均性能比折半查找要好的多。 反之数组中如果分布非常不均匀那可以选折半二分 分块查找
当数据表中的数据元素很多时可以采用分块查找。 汲取了顺序查找和折半查找各自的优点既有动态结构又适于快速查找 分块查找适用于数据较多但是数据不会发生变化的情况如果需要一边添加一边查找建议使用哈希查找 分块查找的过程
需要把数据分成N多小块块与块之间不能有数据重复的交集。给每一块创建对象单独存储到数组当中查找数据的时候先在数组查当前数据属于哪一块再到这一块中顺序查找
public class BlockSearchDemo {public static void main(String[] args) {/*分块查找核心思想块内无序块间有序实现步骤1.创建数组blockArr存放每一个块对象的信息2.先查找blockArr确定要查找的数据属于哪一块3.再单独遍历这一块数据即可*/int[] arr {16, 5, 9, 12,21, 18,32, 23, 37, 26, 45, 34,50, 48, 61, 52, 73, 66};//创建三个块的对象Block b1 new Block(21,0,5);Block b2 new Block(45,6,11);Block b3 new Block(73,12,17);//定义数组用来管理三个块的对象索引表Block[] blockArr {b1,b2,b3};//定义一个变量用来记录要查找的元素int number 37;//调用方法传递索引表数组要查找的元素int index getIndex(blockArr,arr,number);//打印一下System.out.println(index);}//利用分块查找的原理查询number的索引private static int getIndex(Block[] blockArr, int[] arr, int number) {//1.确定number是在那一块当中int indexBlock findIndexBlock(blockArr, number);if(indexBlock -1){//表示number不在数组当中return -1;}//2.获取这一块的起始索引和结束索引 --- 30// Block b1 new Block(21,0,5); ---- 0// Block b2 new Block(45,6,11); ---- 1// Block b3 new Block(73,12,17); ---- 2int startIndex blockArr[indexBlock].getStartIndex();int endIndex blockArr[indexBlock].getEndIndex();//3.遍历for (int i startIndex; i endIndex; i) {if(arr[i] number){return i;}}return -1;}//定义一个方法用来确定number在哪一块当中public static int findIndexBlock(Block[] blockArr,int number){ //100//从0索引开始遍历blockArr如果number小于max那么就表示number是在这一块当中的for (int i 0; i blockArr.length; i) {if(number blockArr[i].getMax()){return i;}}return -1;}
}class Block{private int max;//最大值private int startIndex;//起始索引private int endIndex;//结束索引//省略 构造 属性 等 JavaBean
}哈希查找
树表查找
第二部分排序算法
冒泡排序
Bubble Sort 数值之间 两两比较 找到最大的数 放到最后 第二轮开始以此类推 从0-倒数第二 再开始比较 即不再管最后一个数[依次找得到最大数] private static void bubbleSort() {Random random new Random();int[] arr new int[10000];for (int i 0; i arr.length; i) {arr[i] random.nextInt(1000);}long start System.currentTimeMillis();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;}}}long end System.currentTimeMillis();System.out.println(end - start);for (int i 0; i arr.length; i) {System.out.print(arr[i] );}}重复的遍历过要排序的数列一次比较相邻的两个元素如果他们的顺序错误就把他们交换过来。 总结步骤
相邻的元素两两比较大的放右边小的放左边第一轮比较完毕之后最大值就已经确定第二轮可以少循环一次后面以此类推如果数组中有n个数据总共我们只要执行n-1轮的代码就可以
public class BubbleDemo {public static void main(String[] args) {/*冒泡排序核心思想1相邻的元素两两比较大的放右边小的放左边。2第一轮比较完毕之后最大值就已经确定第二轮可以少循环一次后面以此类推。3如果数组中有n个数据总共我们只要执行n-1轮的代码就可以。*///1.定义数组int[] arr {2, 4, 5, 3, 1};//2.利用冒泡排序将数组中的数据变成 1 2 3 4 5//外循环表示我要执行多少轮。 如果有n个数据那么执行n - 1 轮for (int i 0; i arr.length - 1; i) {//内循环每一轮中我如何比较数据并找到当前的最大值//-1为了防止索引越界//-i提高效率每一轮执行的次数应该比上一轮少一次。for (int j 0; j arr.length - 1 - i; j) {//i 依次表示数组中的每一个索引0 1 2 3 4if(arr[j] arr[j 1]){int temp arr[j];arr[j] arr[j 1];arr[j 1] temp;}}}printArr(arr);}private static void printArr(int[] arr) {//3.遍历数组for (int i 0; i arr.length; i) {System.out.print(arr[i] );}System.out.println();}
}选择排序 找到最小的数 排在最前面 第一轮 0索引位置的数 与后面的数依次比较 找到最小的互换位置 第二轮 1索引位置的数 与… 以此循环 注意内循环 是从1 开始 所以 arr.length不减1 //for (int i 0; i arr.length - 1; i) {
// if (arr[0] arr[i 1]) {
// int temp arr[0];
// arr[0] arr[i 1];
// arr[i 1] temp;
// }
//}
//
//for (int i 1; i arr.length - 1; i) {
// if (arr[1] arr[i 1]) {
// int temp arr[1];
// arr[1] arr[i 1];
// arr[i 1] temp;
// }
//}// 关于为什么 (j 1 i) :
//① i 0 - j 1 ~ 5
//② i 1 - j 2 ~ 5
//...
for (int i 0; i arr.length - 1; i) {for (int j 1 i; j arr.length; j) {if (arr[i] arr[j]) {int temp arr[i];arr[i] arr[j];arr[j] temp;}}
}private static void selectionSort() {int[] arr {2, 4, 5, 3, 1};for (int i 0; i arr.length - 1; i) {for (int j 1 i; j arr.length; j) {if (arr[i] arr[j]) {int temp arr[i];arr[i] arr[j];arr[j] temp;}}}for (int i 0; i arr.length; i) {System.out.print(arr[i] );}}
总结步骤
从0索引开始跟后面的元素一一比较小的放前面大的放后面第一次循环结束后最小的数据已经确定第二次循环从1索引开始以此类推第三轮循环从2索引开始以此类推第四轮循环从3索引开始以此类推。
public class SelectionDemo {public static void main(String[] args) {/*选择排序1从0索引开始跟后面的元素一一比较。2小的放前面大的放后面。3第一次循环结束后最小的数据已经确定。4第二次循环从1索引开始以此类推。*///1.定义数组int[] arr {2, 4, 5, 3, 1};//2.利用选择排序让数组变成 1 2 3 4 5/* //第一轮//从0索引开始跟后面的元素一一比较。for (int i 0 1; i arr.length; i) {//拿着0索引跟后面的数据进行比较if(arr[0] arr[i]){int temp arr[0];arr[0] arr[i];arr[i] temp;}}*///最终代码//外循环几轮//i:表示这一轮中我拿着哪个索引上的数据跟后面的数据进行比较并交换for (int i 0; i arr.length -1; i) {//内循环每一轮我要干什么事情//拿着i跟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;}}}printArr(arr);}private static void printArr(int[] arr) {//3.遍历数组for (int i 0; i arr.length; i) {System.out.print(arr[i] );}System.out.println();}
}
插入排序 首先分为 有序的部分 无序的部分 数据 无序的部分第一个数 依次 与有序的数据 倒序进行对比 然后将无序的部分插入到有序的适当位置 依次循环 每个无序的第一个数 与有序的倒序 对比 加入到有序的部分 中 其实就是 跟它的前一个数对比 交换位置 int[] arr {3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48};//1.找到无序的部分
int startIndex -1;
for (int i 0; i arr.length; i) {if (arr[i] arr[i 1]) {startIndex i 1;break;}
}//2.遍历无序 (可以用while 或者 for) 用while 比较清晰
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 j i; j 0 arr[j] arr[j - 1]; j--) {int temp arr[j];arr[j] arr[j - 1];arr[j - 1] temp;}
}插入排序在插入的时候有优化算法在遍历有序序列找正确位置时可以采取二分查找 private static void insertionSorting() {int[] arr {3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48};//1.找到无序的部分的索引头int index findOrderPart(arr);for (int i index; i arr.length; i) {for (int j i; j 0 arr[j] arr[j - 1]; j--) {int temp arr[j];arr[j] arr[j - 1];arr[j - 1] temp;}}for (int i 0; i arr.length; i) {System.out.print(arr[i] );}}private static int findOrderPart(int[] arr) {for (int i 0; i arr.length; i) {if (arr[i] arr[i 1]) {return i 1;}}return -1;}public class InsertDemo {public static void main(String[] args) {/*插入排序将0索引的元素到N索引的元素看做是有序的把N1索引的元素到最后一个当成是无序的。遍历无序的数据将遍历到的元素插入有序序列中适当的位置如遇到相同数据插在后面。N的范围0~最大索引*/int[] arr {3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48};//1.找到无序的哪一组数组是从哪个索引开始的。 2int startIndex -1;for (int i 0; i arr.length; i) {if(arr[i] arr[i 1]){startIndex i 1;break;}}//2.遍历从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--;}}printArr(arr);}private static void printArr(int[] arr) {//3.遍历数组for (int i 0; i arr.length; i) {System.out.print(arr[i] );}System.out.println();}}快速排序
定义两个索引从前往后 寻找 比基准数大的 // 从后往前 寻找 比基准数小的 -- 找到两个索引交换位置直到 两个索引交汇在同一个数值索引位置上 为止之后 这个交汇位置的值 与 基准数 进行交换以上为一轮交换逻辑。循环使用递归方法进行排序 以基准数为分界线分为两部分两次递归 重复排序 private static void quickSort(int[] arr, int i, int j) {int start i;int end j;if (start end) {return;}int baseNum arr[i];while (start ! end) {while (true) {if (start end || arr[end] baseNum) {break;}end--;}while (true) {if (start end || arr[start] baseNum) {break;}start;}int temp arr[start];arr[start] arr[end];arr[end] temp;}int temp arr[i];arr[i] arr[start];arr[start] temp;quickSort(arr, i, start - 1);quickSort(arr, start 1, j);}总结步骤
从数列中挑出一个元素一般都是左边第一个数字称为 “基准数”;创建两个指针一个从前往后走一个从后往前走。先执行后面的指针找出第一个比基准数小的数字再执行前面的指针找出第一个比基准数大的数字交换两个指针指向的数字直到两个指针相遇将基准数跟指针指向位置的数字交换位置称之为基准数归位。第一轮结束之后基准数左边的数字都是比基准数小的基准数右边的数字都是比基准数大的。把基准数左边看做一个序列把基准数右边看做一个序列按照刚刚的规则递归排序
public class QuickSortDemo {public static void main(String[] args) {System.out.println(Integer.MAX_VALUE);System.out.println(Integer.MIN_VALUE);/*快速排序第一轮以0索引的数字为基准数确定基准数在数组中正确的位置。比基准数小的全部在左边比基准数大的全部在右边。后面以此类推。*/int[] arr {6, 1, 2, 7, 9, 3, 4, 5, 10, 8};//int[] arr new int[1000000];/* Random r new Random();for (int i 0; i arr.length; i) {arr[i] r.nextInt();}*/long start System.currentTimeMillis();quickSort(arr, 0, arr.length - 1);long end System.currentTimeMillis();System.out.println(end - start);//149System.out.println(Arrays.toString(arr));//课堂练习//我们可以利用相同的办法去测试一下选择排序冒泡排序以及插入排序运行的效率//得到一个结论快速排序真的非常快。/* for (int i 0; i arr.length; i) {System.out.print(arr[i] );}*/}/** 参数一我们要排序的数组* 参数二要排序数组的起始索引* 参数三要排序数组的结束索引* */public static void quickSort(int[] arr, int i, int j) {//定义两个变量记录要查找的范围int start i;int end j;if(start end){//递归的出口return;}//记录基准数int baseNumber arr[i];//利用循环找到要交换的数字while(start ! end){//利用end从后往前开始找找比基准数小的数字//int[] arr {1, 6, 2, 7, 9, 3, 4, 5, 10, 8};while(true){if(end start || arr[end] baseNumber){break;}end--;}System.out.println(end);//利用start从前往后找找比基准数大的数字while(true){if(end start || arr[start] baseNumber){break;}start;}//把end和start指向的元素进行交换int temp arr[start];arr[start] arr[end];arr[end] temp;}//当start和end指向了同一个元素的时候那么上面的循环就会结束//表示已经找到了基准数在数组中应存入的位置//基准数归位//就是拿着这个范围中的第一个数字跟start指向的元素进行交换int temp arr[i];arr[i] arr[start];arr[start] temp;//确定6左边的范围重复刚刚所做的事情quickSort(arr,i,start - 1);//确定6右边的范围重复刚刚所做的事情quickSort(arr,start 1,j);}
}总结