数组与排序练习
练习1
// /需求:公司年销售额求和
// 某公司按照季度和月份统计的数据如下:单位(万元)
// 第一季度: 22, 66, 44
// 第二季度: 77, 33, 88
// 第三季度: 25, 45, 65
// 第四季度: 11, 66, 99/
案例代码:
public static void main(String[] args) {
/*需求:公司年销售额求和
某公司按照季度和月份统计的数据如下:单位(万元)
第一季度: 22, 66, 44
第二季度: 77, 33, 88
第三季度: 25, 45, 65
第四季度: 11, 66, 99*/
int[][] arr = {{22, 66, 44}, {77, 33, 88}, {25, 45, 65}, {11, 66, 99}};
//遍历二维数组,对元素进行累加求和
int sums=0;
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
sums+=arr[i][j];
}
}
System.out.println("总销售额是:"+sums+"万元");
}
练习2
//杨辉三角
/*
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1*/
案例代码:
public static void main(String[] args) {
//杨辉三角
/*
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
*/
Scanner scanner = new Scanner(System.in);
System.out.println("请输入你要打印的行数:");
int n = scanner.nextInt();
int[][] arr = new int[n][n];
for (int i = 0; i < arr.length; i++) {
arr[i][0] = 1;
arr[i][i] = 1;
}
//从第三行开始,从第二列开始,这个数字等于他上一行的前一列和上一行的本列之和
for (int i = 2; i < arr.length; i++) {
for (int j = 1; j <= i; j++) {
arr[i][j] = arr[i-1][j-1]+arr[i-1][j];
}
}
//遍历数组
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j <= i; j++) {
System.out.print(arr[i][j] + "\t");
}
System.out.println();
}
}
练习3
需求:根据数组元素查找出该元素第一次在数组中出现的索引
方式1:遍历数组挨个去查找
方式2:二分查找
案例1:
package com.wyy.array;
public class ArrayDemo11 {
public static void main(String[] args) {
//定义一个数组
int[] arr = {10, 20, 70, 1, 90, 100, 1, 2};
//据元素查找出该元素在数组中第一次出的索引
int index = getIndexByElE(arr, 10);
System.out.println("该元素第一次在数组中出现的索引是:"+index);
}
private static int getIndexByElE(int[] arr, int ele) {
//遍历数组查询
for (int i = 0; i < arr.length; i++) {
if (ele==arr[i]){
return i;
}
}
return -1;//如果我们没有找到这个元素那么就返回-1
}
}
案例2
package com.wyy.array;
public class ArrayDemo12 {
public static void main(String[] args) {
//二分查找,前提是数组元素必须优先,如果没有顺序,那么得使用基本查找
int[] arr = {10, 20, 30, 40, 50, 60, 70, 80, 96};
int index = getIndexByElE(arr, 50);
System.out.println("该元素出现的索引是:"+index);
}
private static int getIndexByElE(int[] arr, int ele) {
//定义最下小索引,中间索引,最大索引
int minIndex = 0;
int maxIndex = arr.length - 1;
int centeIndex = (minIndex + maxIndex) / 2;
while (minIndex <= maxIndex) {
//如果说你要找的这个元素,正好等于中间索引所对应的元素,那么就返回中间索引
if (ele == arr[centeIndex]) {
return centeIndex;
//如果你要找的元素大于EEEE对应的元素,你就移动最小索引
} else if (ele > arr[centeIndex]) {
minIndex = centeIndex + 1;
//如果你要找的这个元素小于中间索引所对应的元素,你就移动最大索引
} else if (ele < arr[centeIndex]) {
maxIndex = centeIndex - 1;
}
//重新计算中间索引
centeIndex = (minIndex + maxIndex) / 2;
}
return -1;//没找到就返回-1
}
}
练习4
冒泡排序
案例代码:
package com.wyy.array;
import java.util.Arrays;
public class ArrayDemo13 {
public static void main(String[] args) {
//排序原理:数组元素两两比较,交换位置,大元素往后放
// "那么经过一轮比较后,最大的元素,就会出现在最大索引处。
int[] arr = {24, 69, 80, 57, 13,15,20};//待排序数组
for (int j = 0; j < arr.length-1; j++) {
//如果不使用for循环进行嵌套的话买这个for循环的代码需要跑四遍比较
for (int i = 0; i < arr.length-1-j; i++) {
if(arr[i]>arr[i+1]){
//交换位置
int t = arr[i+1];
arr[i+1]=arr[i];
arr[i] =t;
}
}
}
System.out.println(Arrays.toString(arr));
}
}
练习5
数组之选择排序
排序原理:从0索引处开始,依次和后面的元素进行比较,小的元素往前放,经过一轮比]较后,最小的元素就出现在了最小索引处
案例代碼:
package com.wyy.array;
import java.util.Arrays;
public class ArrayDemo14 {
public static void main(String[] args) {
//选择排序原理:从0索引处开始,依次和后面的元素进行比较,小的元素往前放,经过一轮比较后,最小的元素就出现在了最小索引处
int[] arr = {24, 69, 80, 57, 13, 1, 0, 2};
//
for (int j = 0; j < arr.length; j++) {
for (int i = 1 + j; i < arr.length; i++) {
if (arr[j] > arr[i]) {
int t = arr[j];
arr[j] = arr[i];
arr[i] = t;
}
}
}
System.out.println(Arrays.toString(arr));
}
}
练习6
数组之直接插入排序
排序原理:算法思路:直接插入排序是一种最简单的排序方法他的基本操作是将一个记录插入到一个长度为m的有序表中,使之仍保持有序。
例如:
49,38,65,97,76,13,27原始数据
[49],38,65,97,76,13,27从1索引开始插入
[38,49],65,97,76,13,27
[38,49,65] 97,76,13,27
[38,49,65,97] 76,13,27
[38,49,65,76,97]13,27
[13,27,38,49,65,76,97],27
[13,27,38,49,65,76,97]
案例代码
package com.wyy.array;
import java.util.Arrays;
public class ArrayDemo15 {
public static void main(String[] args) {
//直接插入排序:从1索引处开始,将后面的元素,插入之前的有序列表中使之仍保持有序
int[] arr = {3, 2, 1, 0, 10, 20, 30, 7, 81,-1,200,100};
//外层循环定义伦次
for (int i = 1; i < arr.length; i++) {
//里曾循环进行比较插入
int j =i;
while (j>0 && arr[j] < arr[j-1]){
int t =arr[j];
arr[j] = arr[j-1];
arr[j-1] = t;
j--;
}
}
System.out.println(Arrays.toString(arr));
}
}
练习7
希尔排序算法原理
希尔排序又称缩小增量排序。
- 基本思想:先将原表按增量ht分组,每个子文件按照直接插入法排序。同样,用下一个增量ht/2将文件再分为子文件,再直接插入法排序。直到ht=1时整个文件排好序。
- 关键:选择合适的增量。
- 希尔排序算法9-3:可以通过三重循环来实现。
案例代码
package com.wyy.array;
import java.util.Arrays;
public class ArrayDemo16 {
public static void main(String[] args) {
//希尔排序:他是对插入排序的一个优化,核心的思想就是合理的选取增量,经过一轮排序后,就会让序列大致有序
//然后再不断的缩小增量,进行插入排序,直到增量为1那整个排序结束
//直接插入排序,其实就是增量为1的希尔排序
int[] arr = {46, 55, 13, 42, 17, 94, 5, 70, 1, 2, 3, 4, 6, 9, 25};
shellSort(arr);
System.out.println(Arrays.toString(arr));
}
private static void shellSort(int[] arr) {
//定义一个增量
// //第一轮
// int h = 4;
// for (int i = h; i < arr.length; i++) {
// //里曾循环进行比较插入
// for (int j = i; j > h-1; j-=h) {
// if (arr[j] < arr[j - h]) {
// swapValue(arr, j, j - h);
// }
// }
// }
// //第二轮
// h = 2;
// for (int i = h; i < arr.length; i++) {
// //里曾循环进行比较插入
// for (int j = i; j > h-1; j-=h) {
// if (arr[j] < arr[j - h]) {
// swapValue(arr, j, j - h);
// }
// }
// }
// //第三轮
// h = 1;
// for (int i = h; i < arr.length; i++) {
// //里曾循环进行比较插入
// for (int j = i; j > h-1; j-=h) {
// if (arr[j] < arr[j - h]) {
// swapValue(arr, j, j - h);
// }
// }
// }
//简化
// for (int h = 4; h > 0; h /= 2) {
// for (int i = h; i < arr.length; i++) {
// //里曾循环进行比较插入
// for (int j = i; j > h - 1; j -= h) {
// if (arr[j] < arr[j - h]) {
// swapValue(arr, j, j - h);
// }
// }
// }
// }
//希尔排序的思想,合理的选取这个增量
//第一次这行层楼选取数组长度的一般,然后不断的减半
// for (int h = arr.length / 2; h > 0; h /= 2) {
// for (int i = h; i < arr.length; i++) {
// //里曾循环进行比较插入
// for (int j = i; j > h - 1; j -= h) {
// if (arr[j] < arr[j - h]) {
// swapValue(arr, j, j - h);
// }
// }
// }
// }
//我们第一次的增量选择数组长度的一半,还不是很好,我们可以使用一种序列叫做克努特序列
// int h=1;
// h=h*3+1;//1,4,13,40,121, 364
int interval=1;
while (interval <= arr.length/3){
interval =interval*3+1;
}
for (int h = interval ; h > 0; h =(h-1)/3) {
for (int i = h; i < arr.length; i++) {
//里曾循环进行比较插入
for (int j = i; j > h - 1; j -= h) {
if (arr[j] < arr[j - h]) {
swapValue(arr, j, j - h);
}
}
}
}
}
private static void swapValue(int[] arr, int i, int j) {
int t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
}
练习8
- 快速排序算法思想
分治法:比大小,再分区
1,从数组中取出一个数,作为基准数。
2,分区:将比这个数大或等于的数全放到他的右边,小于他的数全放到他的左边。
3再对左右区间重复第二步,直到各区间只有一个数。
- 挖坑填数
1,将基准数挖出形成第一个坑。
2,由后向前找比他小的数,找到后挖出此数填到前一个坑中。
3, 由前向后找比他大或等于的数,找到后也挖出此数填到前一个坑中。
4,再重复执行2, 3两步骤。
例如对5391672408进行排序
案例代码
package com.wyy.array;
import java.util.Arrays;
public class ArrayDemo17 {
public static void main(String[] args) {
//定义一个数组
int[] arr = {10,3,5,6,1,0, 100,40, 50, 8};
//调用工且举进行快速排序传入数组,传入起始位置,传入结束位置
QuickSortUtils.quickSort(arr, 0, arr.length - 1);
//输出排序后的结果
System.out.println(Arrays.toString(arr));
}
}
package com.wyy.array;
public class QuickSortUtils {
//快速排序Q
public static void quickSort(int[] arr, int start, int end) {
//找出分左右两区的的索引位置,然后对左右两区进行递归调用
if (start<end){
int index = getIndex(arr, start, end);
quickSort(arr,start,index-1);
quickSort(arr, index + 1, end);
}
}
//将基准数挖出形成第一个坑。
//由后向前找比他小的数,找到后挖出此数填到前一个坑中。
//由前向后找比他大或等于的数,找到后也挖出此数填到前一个坑中。
//再重复执行2, 3两步骤。
private static int getIndex(int[] arr, int start, int end) {
int i=start;
int j = end;
int x =arr[i];
while (i<j){
//由后向前找比他小的数,找到后挖出此数填到前一个坑中。
while (i<j&& arr[j]>=x){
j--;
}
if (i<j){
arr[i] =arr[j];
i++;
}
//由前向后找比他大或等于的数,找到后也挖出此数填到前一个坑中。
while (i<j&& arr[i]<x){
i++;
}
if (i<j){
arr[j] =arr[i];
j--;
}
}
arr[i] = x;
return i;
}
}
练习9
归并排序算法思想
归并排序(Merge Sort)就是利用归并的思想实现排序的方法。
它的原理是假设初始序列有N个记录,则可以看成是N个有序的子序列,每个子序列的长度为1,然后两两归并,得到N/2个长度为2或1的有序子序列,再两两归并….
如此重复,直至得到一个长度为N的有序序列为止,这种排序方法称为2路归并排序。
案例代码
package com.wyy.array;
import java.util.Arrays;
public class ArrayDemo18 {
public static void main(String[] args) {
//原始待排序数组
int[] arr = {10, 30, 2, 1, 0, 8, 7, 5, 19, 29,-1,-2,-3};
//我们先给一个左右两边是有序的一个数组,先来进行归并操作
// int[] arr = {4,5,7,8,1,2,3,6};
//拆分
chaifen(arr,0,arr.length-1);
//归并
// guiBing(arr,0,3,arr.length-1);
//输出愿数组
System.out.println(Arrays.toString(arr));
}
private static void chaifen(int[] arr, int startIndex, int endIndex) {
//计算中间 索引
int centerIndex = (startIndex+endIndex)/2;
if (startIndex<endIndex){
chaifen(arr,startIndex,centerIndex);
chaifen(arr,centerIndex+1,endIndex);
guiBing(arr,startIndex,centerIndex,endIndex);
}
}
private static void guiBing(int[] arr, int startIndex, int centerIndex, int endIndex) {
//定义一个临时数组
int[] temArr = new int[endIndex - startIndex + 1];
//定义左边数组的起始索引
int i =startIndex;
//定义右边数组的起始索引
int j = centerIndex+1;
//定义临时数组的起始索引
int index = 0;
//比较左右两个数组的元素大小,往临时数组中放
while (i<=centerIndex && j <= endIndex){
if (arr[i]<=arr[j]){
temArr[index] = arr[i];
i++;
}else{
temArr[index] = arr[j];
j++;
}
index++;
}
//处理剩余元素
while (i<=centerIndex){
temArr[index]=arr[i];
i++;
index++;
}
while (j <= endIndex){
temArr[index]=arr[j];
j++;
index++;
}
// System.out.println(Arrays.toString(temArr));
//将临时数组中的元素取到原数组中
for (int k = 0; k < temArr.length; k++) {
arr[k+startIndex]=temArr[k];
}
}
}
练习10
基数排序
基数排序不同于之前所介绍的各类排序,前边介绍到的排序方法或多或少的是通过使用比较和移动记录来实现排序,而基数排序的实现不需要进行对关键字的比较,只需要对关键字进行“分配"与"收集"两种操作即可完成。
案例代码
package com.wyy.array;
import java.util.Arrays;
public class ArrayDemo19 {
public static void main(String[] args) {
//基数排序:通过分配再收集的方式进行排序
int[] arr = {2, 1, 5, 21, 31, 444, 23, 33, 47, 19, 993, 124, 987, 1991, 23, 33, 100000};
//待确定排序伦次
//获取数组中的最大值
// int max = getMax(arr);
//基数排序
sortArray(arr);
//输出排序过后的数组
System.out.println(Arrays.toString(arr));
}
private static void sortArray(int[] arr) {
//定义二维数组,放10个桶
int[][] temArr = new int[10][arr.length];
//定义一个统计数组
int[] counts = new int[10];
int max = getMax(arr);
int len = String.valueOf(max).length();
//循环轮次
for (int i = 0, n = 1; i < len; i++, n *= 10) {
for (int j = 0; j < arr.length; j++) {
//获取每个位置上的数字
int ys = arr[j] / n % 10;
temArr[ys][counts[ys]++] = arr[j];
}
//取出桶中的元素
int index = 0;
for (int k = 0; k < counts.length; k++) {
if (counts[k] != 0) {
for (int h = 0; h < counts[k]; h++) {
//从桶中取出元素放回原数组
arr[index] = temArr[k][h];
index++;
}
//清楚上一次统计的个数
counts[k] = 0;
}
}
}
}
private static int getMax(int[] arr) {
int max = arr[0];
for (int i = 0; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
return max;
}
}
练习11
堆排序
堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序堆
排序的基本思想是:
1将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。
2将其与末尾元素进行交换,此时末尾就为最大值。
3然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。
4如此反复执行,便能得到一个有序序列了.
案例代码
package com.wyy.array;
import java.util.Arrays;
public class ArrayDemo20 {
public static void main(String[] args) {
//定义一个数组
int[] arr = {1, 0, 6, 7, 2, 3, 4,3,6,7,8,90,21};
//调整成大顶推方法
//定义开始调整的位置
int startIndex = (arr.length - 1) / 2;
//循环开始调
for (int i = startIndex; i >= 0; i--) {
toMaxHeap(arr, arr.length, i);
}
//经过上面的操作后,已经把数组变成一个大顶堆,把根元素和最后一个元素进行调换
for (int i =arr.length-1;i>0; i--) {
//进行调换
int t =arr[0];
arr[0] =arr[i];
arr[i] =t;
//换完之后,我们在把剩余元素调成大顶锥
toMaxHeap(arr,i,0);
}
System.out.println(Arrays.toString(arr));
}
/*
@param arr 要排序的数组
@param size 调整的元素个数
@param index 从哪里开始调整
*/
private static void toMaxHeap(int[] arr, int size, int index) {
//获取左右字节的索引
int lefNodeIndex = index * 2 + 1;
int rightNodeIndex = index * 2 + 2;
//查找最大节点所对应的索引
int maxIndex = index;
if (lefNodeIndex < size && arr[lefNodeIndex] > arr[maxIndex]) {
maxIndex = lefNodeIndex;
}
if (rightNodeIndex < size && arr[rightNodeIndex] > arr[maxIndex]) {
maxIndex = rightNodeIndex;
}
//我们来调换位置
if (maxIndex != index) {
int t = arr[maxIndex];
arr[maxIndex] = arr[index];
arr[index] = t;
//调换完之后,可能会影响到,下面的子树,不是大顶堆,我们还需要再次调换
toMaxHeap(arr, size, maxIndex);
}
}
}