数组
数组
Array,多个相同类型数据按一定顺序排列的集合,使用一个名字命名,并通过编号的方式对数据进行统一管理
1. 数组特点
- 数组是有序排列的
- 数组是引用数据类型变量
- 在内存中是一组连续的空间
- 数组长度一旦确定就不可修改
2. 一维数组使用
一维数组的声明和初始化
如何调用数组的指定位置的元素
如何获取数组的长度
如何遍历数组
数组元素的默认初始化值
数组的内存解析
-
声明 和 初始化
int[] ids;//声明 //静态初始化 ids = new int[]{1,2,3,4} int[] arr = {1,2,3,4,5}//类型推断 //动态初始化 String[] names = new String[5];
-
调用指定位置元素
String[] names = new String[5]; names[0] = "a"; names[1] = "a"; names[2] = "a"; names[3] = "a"; names[4] = "a";
-
获取数组长度
names.length
-
遍历数组
String[] names = new String[]{"a","b","c","d"}; for (int i = 0; i < names.length; i++) { System.out.println(names[i]); }
-
数组元素的默认初始化值
整型: 0 浮点型: 0.0 char型: 0或'\u0000' boolean型: false 引用类型: null
-
数组的内存解析
3.多维数组的使用
- 声明和初始化
//静态初始化 int[][] arr1 = new int[][]{{1,2,3},{4,5},{6,7,8}} int[][] arr1 = {{1,2,3},{4,5},{6,7,8}}//类型推断 //动态初始化 String[][] arr2 = new String[3][2]; //动态初始化 String[][] arr3 = new String[3][];
- 获取指定位置数据
arr1[1][1]
- 获取数组长度
arr.length arr[0].length
- 遍历二维数组
for(int i = 0; j < arr.length; i++){ for(int j = 0; j < arr[i].length; j++){ System.out.print(arr[i][j] + " ") } System.out.println(); }
- 数组元素的默认初始化值
初始化方式一:int[][] arr = new int[4][3] 外层元素的初始化值为:地址值 内存元素的初始化值为:同一维数组初始化情况相同 初始化方式一:int[][] arr = new int[4][] 外层元素的初始化值为:null 内层元素的初始化值为:不能调用,否则报错。
练习
1.查找类练习
杨辉三角
打印10行杨辉三角
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
1 7 21 35 35 21 7 1
1 8 28 56 70 56 28 8 1
1 9 36 84 126 126 84 36 9 1
//1.声明二维数组
int[][] yangHui = new int[10][];
//2.给数组赋值
for (int i = 0; i < yangHui.length; i++) {
yangHui[i] = new int[i + 1];
yangHui[i][0] = yangHui[i][i] = 1;
for (int j = 1; j < yangHui[i].length - 1; j++) {
yangHui[i][j] = yangHui[i-1][j-1] + yangHui[i-1][j];
}
}
//3.遍历二维数组
for (int i = 0; i < yangHui.length; i++) {
for (int j = 0; j < yangHui[i].length; j++) {
System.out.print(yangHui[i][j] + "\t");
}
System.out.println();
}
回形数
2.获取数组元素中的最大,最小,平均值等
最大,最小,和,平均
int[] arr = new int[10];
//[10,99]
//(int)(Math.random() * (99 - 10 + 1) + 10)
for (int i = 0; i < arr.length; i++) {
arr[i] = (int)(Math.random() * (99 - 10 + 1) + 10);
}
//最大值
int maxValue = arr[0];
for (int i = 0; i < arr.length; i++) {
if (maxValue < arr[i]){
maxValue = arr[i];
}
}
System.out.println(maxValue);
//最小值
int minValue = arr[0];
for (int i = 0; i < arr.length; i++) {
if (minValue > arr[i]){
minValue = arr[i];
}
}
System.out.println(minValue);
//和
int sum = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}
System.out.println(sum);
//平均
double avg = 0;
avg = sum* 1.0/arr.length ;
System.out.println(avg);
3.数组的复制,反转,查找(线性查找,二分法查找)
数组复制
String[] arr1 = new String[]{"JJ","DD","MM","BB","GG","AAA"};
String[] arr2 = new String[arr1.length];
for(int i = 0; i < arr1.length; i++){
arr2[i] = arr1[i];
}
数组反转
for(int i = 0; i < arr.length / 2; i++){
String temp = arr[i];
arr[i] = arr[arr.length - i - 1];
arr[arr.length - i -1] = temp;
}
for(int i = 0; j = arr.length - 1; i < j; i++,j--){
String temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
数组查找
int[] arr = new int[]{0,1,2,3,4,5,6,7,8,9,11};
int dest = 4;
int head = 0;
int end = arr.length - 1;
boolean isFlag = true;
while(head <= end){
int middle = (head + end)/2;
if(dest == arr[middle]){
isFalg = false;
break;
}else if(arr[middle] > dest){
end = middle - 1;
}else {
head = middle + 1;
}
}
if(isFlag){
System.out.println("not find");
}
4.数组排序
十大内部排序算法
- 选择排序
直接选择排序、堆排序 - 交换排序
冒泡排序、快速排序 - 插入排序
直接插入排序、折半插入排序、Shell排序 - 归并排序
- 桶式排序
- 基数排序
冒泡排序
/**
* 冒泡排序
*/
@Test
public void test4() {
int[] arr = new int[]{1, 9, 2, 8, 3, 7, 5, 4};
//冒泡次数
for (int i = 0; i < arr.length - 1; i++) {
for (int j = i; 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.println( "第" + i + "轮 : " + Arrays.toString(arr));
}
System.out.println(Arrays.toString(arr));
}
插入排序
/**
* 插入排序
* 从后往前插
*/
@Test
public void test3() {
int[] arr = new int[]{19, 122, 23, 139, 41, 43, 124};
//从第二个数开始向前插入
for (int i = 1; i < arr.length; i++) {
int nowdata = arr[i];//记录要插入的数值
/*
k = i - 1: 说明k是从 需要插入的目标值前一位,到数组开头
k >= 0: 循环查找已排好序的数组索引的最前方,最小只到 0 索引
arr[k] > nowdata : 只要前方比较的值大于目标值就 还没到 目标位置,
*/
int k = 0;
for (k = i - 1; k >= 0 && arr[k] > nowdata; k--) {
arr[k + 1] = arr[k];//为找到目标位置,将数组想目标值移动一格
}
arr[k + 1] = nowdata;//将目标值放入到目标位置上
}
System.out.println(Arrays.toString(arr));
}
选择排序
@Test
public void test6() {
int[] arr = new int[]{1, 9, 2, 8, 3, 7, 5, 4};
//最多 找数组长度减一次
for (int i = 0; i < arr.length - 1; i ++ ){
int max_id = i;//第I个数
for (int j = i + 1; j < arr.length; j++) {
//找到最大值的索引
if (arr[j] > arr[max_id]){
max_id = j;
}
}
if (max_id != i){
int temp = arr[i];
arr[i] = arr[max_id];
arr[max_id] = temp;
}
}
System.out.println(Arrays.toString(arr));
}
快排
/**
* 快速排序
*/
@Test
public void test9() {
int[] arr = {3,4,5,1,23,3,4,5,6,7,2,4,6,5,4234,22,3,457,34,32};
Quick_sort(arr,0, arr.length - 1);
System.out.println(Arrays.toString(arr));
}
public void Quick_sort(int[] arr, int low, int high) {
if (arr == null || arr.length <= 1) {
return;//不需要
}
if (low < high) {
int mid = getmid(arr, low, high);
Quick_sort(arr, low, mid - 1);
Quick_sort(arr, mid + 1, high);
}
}
public int getmid(int[] arr, int low, int high) {
int temp = arr[low];//第一个数据
while (low < high){
while (low < high && arr[high] >= temp){
high--;//取出左边的一个大于第一个值的数据
}
arr[low] = arr[high];
while (low < high && arr[low] < temp){
low++;//取出最右边的一个小于第一个值的数据
}
arr[high] = arr[low];//填充
}
arr[low] = temp;
//show();
return low;
}
堆排序
/**
* 选出最大值
* arr = [3,1,6,7,8,4,2,9,3,5]
* <p>
* arr[0] = 3
* <p>
* arr[1] = 1 arr[2] = 6
* <p>
* arr[3] = 7 arr[4] = 8 arr[5] = 4 arr[6] = 2
* <p>
* arr[7] = 9 arr[8] = 3 arr[9] = 5
* <p>
* arr[n]
* arr[n*2+1] arr[n*2+2]
*/
public void findmax(int[] arr) {
//从数组的最后开始循环,可以看作从堆的堆底开始向上走
for (int i = arr.length - 1; i > 0; i--) {
// int parent = (i-1)/2; //取出父节点
int parent = i / 2; //取出父节点
int child = i;//记录当前节点
if (i < arr.length - 1 && arr[i] < arr[i + 1]) {
child += 1;
}
if (arr[child] > arr[parent]) {
int temp = arr[child];
arr[child] = arr[parent];
arr[parent] = temp;
}
}
}
public void myfindmax(int[] arr) {
//从数组的最后开始循环,可以看作从堆的堆底开始向上走
for (int i = arr.length - 1; i > 0; i--) {
int parent = (i-1)/2; //计算出当前节点父节点
int child = i; //记录当前节点
//判断当前节点是否为左节点:左节点才比较两子节点大小,再比较父子大小
if (2*parent + 1 == child){
//如果不是最后一点,比较两子节点,得到最大子节点索引
if (i < arr.length - 1 && arr[i] < arr[i + 1]) {
child += 1;
}
if (arr[child] > arr[parent]) {
int temp = arr[child];
arr[child] = arr[parent];
arr[parent] = temp;
}
}
}
}
@Test
public void test7() {
int[] arr = {3, 1, 6, 7, 8, 4, 2, 9, 3, 5};
myfindmax(arr);
// findmax(arr);
System.out.println(Arrays.toString(arr));
}
@Test
public void test8() {
int[] arr = {3, 1, 6, 7, 8, 4, 2, 9, 3, 5};
if (arr == null || arr.length <= 1) {
return;
}
for (int i = 0; i < arr.length - 1; i++) {
int[] newarr = Arrays.copyOfRange(arr, i, arr.length);
findmax(newarr);
for (int j = 0; j < newarr.length; j++) {
arr[i + j] = newarr[j];
}
}
System.out.println(Arrays.toString(arr));
}
二分查找插入
/**
* 可以一边读取文件,一边插入,(找到位置时可以使用二分查找) ---- 二分插入排序法
*/
public class BinsearchInsetSort extends Sort {
public BinsearchInsetSort(int[] data) {
super(data);
}
/**
* 将数据锁定在某一段之间
*/
public void goSort(){
//第一个数不用插,从第二个数开始插入
for(int i = 1; i < data.length;i++){
//插入条件
if (data[i] < data[i - 1]){
int temp = data[i];//保存要插入的值,为数据移动藤出空间
//二分查找
int low = 0; //二分查找的下限
int height = i -1; //二分查找的上限
while (low <= height) {//左右夹逼
int mid = (low + height) / 2;//取中间值
//比较中间值与插入值大小,重新界定查找范围,最终low的位置是插入位置
if (data[mid] < temp) {
low = mid + 1;
} else {
height = mid - 1;
}
}
//循环完毕后该插入的坐标是在low的位置上
//向后移动数组
for (int j = i; j > low; j--){
data[j] = data[j - 1];
}
data[low] = temp;
}
}
}
public static void main(String[] args) {
int[] data = {1,20,3,1,2,3,5,98,43,45,7,5};
// Sort st = new BinsearchInsetSort(data);
Sort st = new MergeSort(data);
st.show();
st.goSort();//对整个数组排序
st.show();
}
}
归并排序
public class Sort {
public int[] data;
public Sort(int[] data) {
this.data = data;
}
public void goSort(){
Arrays.sort(data);
}
public void show(){//显示
for (int i : data){
System.out.print(i + "\t");
}
System.out.println("\n");
}
public void show(int left,int right){//显示
while (left <= right){
System.out.print(this.data[left++] + "\t");
}
System.out.println("\n");
}
}
**
* O(nlog2n)
*/
public class MergeSort extends Sort {
public MergeSort(int[] data) {
super(data);
}
@Override
public void goSort() {
sortit(0, data.length - 1 );
}
void sortit(int left,int right){
if (left >= right){//一个元素终止
return;
}
int center = ( left + right )/2;//切半
sortit(left,center);//左半
sortit(center + 1,right);//右半
//递归放在最下面的是逆序
merge(left,center,right);
// this.show();
}
void merge(int left,int center,int right){
int oldleft = left;
int oldright = right;
System.out.print("归并前:");
show(oldleft,oldright);
//临时数组
int[] temparr = new int[data.length];//归并
int mid = center + 1; //右边数组的第一个元素
int third = left; //缓存数组的 数组索引
int temp = left; //左边数组的索引
//将左右两个的数组 第一个最小的数组打印过来
while (left <= center && mid <= right){
if (data[left] <= data[mid]){
temparr[third++] = data[left++];
} else {
temparr[third++] = data[mid++];
}
}
//将剩余数组归并,接上尾部的一段
while (mid <= right){
temparr[third++] = data[mid++];
}
while (left <= center){
temparr[third++] = data[left++];
}
//归并后的数组拷贝到原来的数组
while (temp <= right){
data[temp] = temparr[temp++];
}
System.out.print("归并后:");
show(oldleft,oldright);
}
}
public static void main(String[] args) {
int[] data = {1,20,3,1,2,3,5,98,43,45,7,5};
Sort st = new MergeSort(data);
st.show();
st.goSort();//对整个数组排序
st.show();
}
桶排序
/**
* 桶排序
*/
public class BuckerSortTest {
public static void bucketsort(int[] ages,int min,int max){
int [] buffer = new int[max - min + 1];
for (int i = 0; i < ages.length;i++){
buffer[ages[i]]++;
}
for (int i = 0,j = 0; i <= max; i++){//i:循环桶, j:循环ages
while (buffer[i]-->0){
ages[j++] = i;
}
}
}
public static void main(String[] args) {
//创建随机数
int[] ages = new int[1000];
for (int i = 0; i < 1000; i++) {
ages[i] = (int) (Math.random() * (100 - 0 + 1));
}
for (int age : ages){
System.out.print(age + "\t");
}
System.out.print("\n");
bucketsort(ages,0,100);
for (int age : ages){
System.out.print(age + "\t");
}
System.out.print("\n");
}
}
基数排序
public class RadixSortTest {
public static void main(String[] args) {
//创建随机数
int[] ages = new int[1000];
for (int i = 0; i < 1000; i++) {
ages[i] = (int) (Math.random() * (9999 - 0 + 1));
}
show(ages);
radixsort(ages);
show(ages);
}
public static void radixsort(int[] data) {
int exp;//位数
int max = getmax(data);
//从个位开始,指数排序
for (exp = 1; max / exp > 0; exp *= 10) {
//按照位数处理
countsort(data, exp);
}
}
public static void countsort(int[] data, int exp) {
int[] output = new int[data.length];//备份
int[] buckets = new int[10];//数据出现的次数保存 0-9
for (int i = 0; i < data.length; i++) {
buckets[(data[i] / exp) % 10]++;
}
//出现的位置
for (int i = 1; i < 10; i++) {
buckets[i] += buckets[i - 1];
}
//数据存储到临时数组
for (int i = data.length - 1; i >= 0; i--) {
output[buckets[(data[i] / exp) % 10] - 1] = data[i];
buckets[(data[i] / exp) % 10]--;
}
//赋值,排序的值给data: 数据拷贝
for (int i = data.length - 1; i >= 0; i--) {
data[i] = output[i];
}
output = null;
buckets = null;
}
//控制台打印
public static void show(int[] data) {
for (int i : data) {
System.out.print(i + "\t");
}
System.out.print("\n");
}
//获取最大值
public static int getmax(int[] data) {
int max = data[0];
for (int i = 1; i < data.length; i++) {
if (data[i] > max) {
max = data[i];
}
}
return max;
}
}
Arrays 工具类
- equals()
- copyOf()
- toString()
- fill()
- binarySearch()
- sort()
/**
* equals
* 需要数据类型相同,数组中元素顺序也相同
*
* copyOf : 数组拷贝
*
* toString :将数组转为打印字符串
*
* fill : 填充方法
*
* binarySearch() : 二分查找法
*/
@Test
public void test1(){
int[] a1 = new int[]{1,2,3,4,5};
int[] a2 = new int[]{1,2,3,4,5};
int[] a3 = new int[]{1,2,3,5,4};
double[] a4 = new double[]{1,2,3,4,5};
System.out.println(Arrays.equals(a1,a2));
System.out.println(Arrays.equals(a1,a3));
// System.out.println(Arrays.equals(a1,a4));
int[] b = Arrays.copyOf(a1, 5);
int[] b2 = Arrays.copyOfRange(a1, 0, 2);
System.out.println(Arrays.toString(b));
System.out.println(Arrays.toString(b2));
int[] c = new int[10];
int[] c2 = new int[10];
Arrays.fill(c,10);
Arrays.fill(c2,1,3,100);
System.out.println(Arrays.toString(c));
System.out.println(Arrays.toString(c2));
int i = Arrays.binarySearch(a3, 5);
System.out.println(i);
}
- parallelSort
- parallelPrefix
- parallelSetAll
/**
* parallelSort : 并发排序
*/
@Test
public void test2(){
int[] arr = new int[64];
for (int i = 0; i < arr.length; i++) {
arr[i] = (int) (Math.random() * (100 - 0 + 1));
}
System.out.println(Arrays.toString(arr));
Arrays.parallelSort(arr);//并发排序,多线程排序
System.out.println(Arrays.toString(arr));
}
/**
* 并发计算 :
*
* parallelPrefix
*
* parallelSetAll
*
*/
@Test
public void test3(){
int[] arr = new int[64];
for (int i = 0; i < arr.length; i++) {
arr[i] = (int) (Math.random() * (100 - 0 + 1));
}
System.out.println(Arrays.toString(arr));
int[] arr2 = Arrays.copyOf(arr, arr.length);
int[] arr3 = Arrays.copyOf(arr, arr.length);
Arrays.parallelSort(arr2);
System.out.println(Arrays.toString(arr2));
//并发相邻计算
Arrays.parallelPrefix(arr, new IntBinaryOperator() {
@Override
public int applyAsInt(int left, int right) {
return left + right;
}
});
System.out.println(Arrays.toString(arr));
Arrays.parallelSetAll(arr3, new IntUnaryOperator() {
@Override
public int applyAsInt(int index) {
return arr3[index] + 2;
}
});
System.out.println(Arrays.toString(arr3));
}