一、数组的定义
变量类型 变量名字 = 变量的值。数组一旦创建,大小不可改变,元素必须相同类型,可以是任何的类型,数组变量属于引用变量,数组对象保存在堆中。静态初始化为创建+赋值、动态初始化为创建+默认初始化(int类型默认0,String类型默认null),例子中a为静态初始化,b为动态初始化。
int[] a = {1,2,3,4,5,6,7,8,9};
int[] b = new int[10];
b[0] = 10;
二、数组的使用
数组一般采用for循环和Arrays工具进行使用。如果采用增强for循环的话,因为增强for没有下标,所以一般用于打印全部数组。Arrays工具其实就是Java前人写好的方法,可以导入java.util.Arrays来进行使用。
int[] b = new int[10];
for(int i = 0;i < b.length;i++){
System.out.print(b[i]);
}//遍历数组
for (int arrary : b){
System.out.print(arrary);
}//遍历数组
System.out.println(Arrays.toString(b));//打印数组元素
Arrays.sort(b);//小到大顺序排序
System.out.println(Arrays.toString(b));
Arrays.fill(b,2,4,0)//把b下标为2和4的元素填充替换为0
System.out.println(Arrays.toString(b));
三、二维数组
二维数组就像一个表格,前一个[]表示第几行,后一个[]表示第几列。
int[][] array = {{1,2},{1,3},{1,4},{1,5}};
System.out.println(array[0]);//1,2
System.out.println(array[0][0]);//1
System.out.println(array.length);//4
System.out.println(array[0].length);//2
四、排序算法
1)冒泡排序
先比较数组中两个相邻的元素,如果第一个数比第二个大(小),就交换位置。每次比较都会产生一个最大或最小的数字,每轮都比上轮少一次排序,依次循环直到结束。
public static int[] sort(int[] array){
int temp;
// 外层循环,判断要走多少次;
for (int i = 0; i < array.length; i++) {
boolean flag = false;//通过flag标识位减少没有意义的比较
// 内层循环,比较判断两个数入股过第一个数,比第二个大,交换位置
for (int j = 0; j <array.length-1 ; j++) {
if (array[j+1]>array[j]){
temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
flag = true;
}
}
if (flag==false){
break;
}
}
return array;
}
2)选择排序
从0索引开始,依次与后面的数进行比较,如果后面的数小于(大于)索引0的数,两数进行交换,使得最小(大)的数出现在最小索引处。每轮比上轮少一次排序,依次到循环结束。
public static int[] sort(int[] arr){
for (int index = 0; index < arr.length-1; index++) {
for (int i = 1+index; i < arr.length; i++) {
if (arr[index]>arr[i]){
int t = arr[index];
arr[index] = arr[i];
arr[i] = t;
}
}
}
return arr;
}
3)插入排序
直接插入排序是一种最简单的排序方法。他将一个记录插入到一个长度为n的有序表中,使之仍保持有序。即从索引1开始依次将后面的数插入有序表中。
private static int[] sort(int[] arr) {
for (int i = 1; i < arr.length; i++) {
for (int j = i;j > 0;j--){
if (arr[j] < arr[j-1]){
int t = arr[j];
arr[j] = arr[j-1];
arr[j-1] = t;
}
}
}
return arr;
}
4)快速排序
比大小,再分区。从数组中取出一个数作为基准数,将比这个数大或等于的数放到他右边,小于他的数放到左边,在对左右区间重复分区,直到每个区间只有一个数。第一轮从后往前找比第一个数小的放入第一个数的位置,第二轮从前往后找比原第一个数大或等于的数放入第一轮找到的数的位置,依次重复到位置重合。
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;
}
5)归并排序
假设初始序列有N个记录,则可以看成是N个有序的子序列,每个子序列的长度为1,然后俩俩归并,得到N/2个长度为2或1的有序子序列,再俩俩归并,如此重复直到得到一个长度为N的有序序列为止。
public static void main(String[] args) {
int[] arr= {4,7,5,8,1,3,9,6,-8,0};
//拆分
chaifen(arr,0,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[] tempArr = 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]){
tempArr[index] = arr[i];
i++;
}else{
tempArr[index] = arr[j];
j++;
}
index++;
}
//处理剩余元素
while (i <= centerIndex){
tempArr[index] = arr[i];
i++;
index++;
}
while (j <= endIndex){
tempArr[index] = arr[j];
j++;
index++;
}
//将临时数组中的元素取到元素组中
for (int k = 0; k < tempArr.length; k++) {
arr[k+startIndex] = tempArr[k];
}
}
6)希尔排序
希尔排序又称缩小增量排序,将个数为n的数组进行俩俩分组,两个数增量(间隔)为n/2,俩俩进行排排序交换位置,使其大致有序后进行下一轮排序,此轮增量为n/4,接下来不断重复缩小增量为n/8,n/16直到增量为1。直接插入排序可以看成是增量为1的希尔排序。这里增量用n/2还不是最优选,可以使用knuth序列来求最优增量(h=h*3+1,初始h=1)。
private static int[] sort(int[] arr) {
int jiange = 1;
while (jiange<arr.length/3){
jiange = jiange * 3 + 1;
}
for (int h = jiange; 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]){
int t = arr[j];
arr[j] = arr[j-h];
arr[j-h] = t;
}
}
}
}
return arr;
}
7)堆排序
把数组从上往下,从左往右放入完全二叉树中,升序转换成大顶堆(父节点大于叶子节点),降序转换为小顶堆。从最后一个非叶子节点开始转,转完换同层的非叶子节点的兄弟转,再换上一层转换,当上一层转换破坏了其子节点的大顶堆状态时,转向该节点继续转换。当该完全二叉树全为大顶堆时,把根节点的元素跟最后一个元素进行交换,使得最后一个叶子节点为最大(小)数,再将剩余节点的重新转换大顶堆状态,重复操作直至结束。
public static void main(String[] args) {
int[] arr = {1,0,6,7,2,3,4};
//定义开始调整的位置
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));
}
private static void toMaxHeap(int[] arr, int size, int index) {
//获取左右子节点的索引
int leftNodeIndex = index * 2 + 1;
int rightNodeIndex = index * 2 + 2;
//查找最大节点所对应的索引
int maxIndex = index;
if (leftNodeIndex < size && arr[leftNodeIndex] > arr[maxIndex]){
maxIndex = leftNodeIndex;
}
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);
}
}
8)基数排序
基数排序与前面的排序不同,基数排序的实现不需要进行对关键字的比较,只需要对关键字进行“分配”和“收集”。先按顺序比较个位数,按数字放入不同组中,再按先进先出从组中取出,接下来比较十位数,放入相应的组中,再次按先进先出从组中取出,不断重复直到最大数的最高位。注意:基数排序不能直接对负数进行排序,可以通过统一加一个数使得每个数都为正数后进行排序,再减去这个数进行输出。
public static void main(String[] args) {
int[] arr= {4,7,5,8,11,3,9,6,8,0,100,120};
//确定排序轮次
//获取数组中的最大值
//基数排序
sort(arr);
//输出排序后的数组
System.out.println(Arrays.toString(arr));
}
private static void sort(int[] arr) {
//定义二维数组放十个组
int[][] tempArr = new int[10][arr.length];
int max = getMax(arr);
int len = String.valueOf(max).length();
//定义统计数组:统计每个组有几个元素
int[] counts = new int[10];
//循环轮次
for (int i = 0,n = 1; i < len; i++,n*=10) {
for (int j = 0; j < arr.length; j++) {
//获取每个位上的数字
int num = arr[j]/n%10;
tempArr[num][counts[num]++] = 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] = tempArr[k][h];
index++;
}
}
counts[k] = 0;//清除上一次的统计
}
}
}
private static int getMax(int[] arr) {
int max = arr[0];
for (int i = 1; i < arr.length; i++) {
if (arr[i]>max){
max = arr[i];
}
}
return max;
}