《数组常见应用》
1. 数组应用——单重循环
数组遍历,求数组中的最大值,求数组元素的和,数组转成字符串,根据下标找数组中的元素,反转数组,进制转换,普通查找,二分查找等
1.1 数组遍历
[I@1afae45:[代表数组,I代表int型,@是分割符,1afae45是(哈希算法算出来的哈希值)地址
/*
* 遍历数组
*/
public static void ergodicArray(){
//定义字符数组
char charArray[] = {'a','b','c','d'};
//方法一
System.out.println(charArray[0]); //a
System.out.println(charArray[1]); //b
System.out.println(charArray[2]); //c
System.out.println(charArray[3]); //d
//数组下标越界 异常
//System.out.println(charArray[4]); //java.lang.ArrayIndexOutOfBoundsException
//方法二
for (int i = 0; i < charArray.length; i++) {
System.out.println(charArray[i]);
}
int intArray[] = {3,6};
//[代表数组,I代表int型,@是分割符,1afae45是(哈希算法算出来的哈希值)地址
System.out.println(intArray); //[I@1afae45
}
1.2 求数组中的最大值
/*
* 求数组中的最大值
*/
public static void getMaxArray(){
int intArray[] = new int[]{3,6,22,9,14};
//将数组中的第一个元素设为最大值
int max = intArray[0];
//所有的数和max比较,遍历数组
for (int i = 0; i < intArray.length; i++) {
//找到比max还大的数,就将这个数赋值给max
if(max < intArray[i]){
max = intArray[i];
}
}
System.out.println("数组中最大数是:"+max); //数组中最大数是:22
}
1.3 求数组元素的和
/*
* 求数组元素的和
*/
public static void getSumArray(){
int intArray[] = new int[]{3,6,22,9,14};
//定义一个变量保存和,初始化赋值0
int sum = 0;
//遍历数组,将所有的元素取出来和sum相加,再将值赋给sum
for (int i = 0; i < intArray.length; i++) {
sum += intArray[i];
}
System.out.println("数组和为:"+sum); //数组和为:54
}
1.4 数组转成字符串
public static void main(String[] args) {
char chars[] = {'H','E','L','L','O',',','J','A','V','A','!'};
String str = arrayToString(chars);
System.out.println(str); // HELLO,JAVA!
}
/*
* 数组转成字符串
*/
public static String arrayToString(char[] chars){
//定义字符串变量
String str = "";
//遍历数组,取出所有的元素与str拼接,再将值赋给str
for (int i = 0; i < chars.length; i++) {
str += chars[i]; // 等价于 str = str +chars[i];
}
return str;
}
1.5 根据下标找数组中的元素
public static void main(String[] args) {
char element = getElement(22);
System.out.println(element);
}
/*
* 根据下标找数组中的元素
*/
public static char getElement(int index){
char chars[] = {'H','E','L','L','O',',','J','A','V','A','!'};
//为了防止数组下标越界
if(index < 0 || index >= chars.length){
System.out.println("下标越界");
return 'F';
}
return chars[index];
}
1.6 反转数组
public static void main(String[] args) {
char chars[] ={'A','B','C','D','E','F'};
print("数组反转前:",chars); //数组反转前:ABCDEF
chars = reverseArray(chars);
print("数组反转后:",chars); //数组反转后:FEDCBA
}
public static char[] reverseArray(char[] chars){
//定义最大下标和最小下标,当最大下标大于最小下标就循环
for (int min =0,max = chars.length -1; min < max ; min++,max--) {
//交换最大下标与最小下标的值
char temp = chars[min];
chars[min] = chars[max];
chars[max] = temp;
}
return chars;
}
public static void print(String message, char[] chars){
System.out.print(message);
for (int i = 0; i < chars.length; i++) {
System.out.print(chars[i]);
}
System.out.println();
}
1.7 进制转换
public class ArrayUse {
public static void main(String[] args) {
int num = 60;
//系统提供的十进制转二进制、八进制、十六进制的方法(使用基本数值数据类型对应包装类)
System.out.println("十进制转二进制:"+Integer.toBinaryString(num));
System.out.println("十进制转八进制:"+Integer.toOctalString(num));
System.out.println("十进制转十六进制:"+Integer.toHexString(num));
//系统提供的二进制、八进制、十六进制转十进制的方法
System.out.println("二进制转十进制:"+Integer.valueOf("111100", 2));
System.out.println("八进制转十进制:"+Integer.valueOf("74", 8));
System.out.println("十六进制转十进制:"+Integer.valueOf("3c", 16));
System.out.println("二进制转十进制:"+Integer.parseInt("111100", 2));
System.out.println("八进制转十进制:"+Integer.parseInt("74", 8));
System.out.println("十六进制转十进制:"+Integer.parseInt("3c", 16));
//自已实现十进制转换其他进制
System.out.println("自实现十进制转二进制:"+toBinaryString(num));
System.out.println("自实现十进制转八进制:"+toOctalString(num));
System.out.println("自实现十进制转十六进制:"+toHexString(num));
}
public static String toBinaryString(int num){
return trans(num,1,1);
}
public static String toOctalString(int num){
return trans(num,3,7);
}
public static String toHexString(int num){
return trans(num,4,15);
}
/**
*
* trans:(转换进制)
*
* @param @param num 转换的数据
* @param @param offset 要转换进制是二进制的指数幂(如十进制转八进制:除以基数8,取余,余数倒排列,即:3)
* @param @param base 要转换进制的组的最大值:二进制是1,八进制是7,十六进制是15
* @param @return 设定文件
* @return String DOM对象
* @throws
* @since CodingExample Ver 1.1
*/
public static String trans(int num,int offset,int base){
//使用字符数组存储转换后的进制
int count = 0;
//定义变量,用于运算获取存取转换后进制的字符数组长度
int num2 = num;
while(num2 != 0){
num2=num2>>>offset;
count++;
}
char chars[] = new char[count];
for (int i = 0; num !=0; i++) {
//解析数字,即得到余数
int k = num&base;
//相当于num更新为2^offset(除以了一个要转换的基数)之后的值
num= num>>>offset;
//把转换后的数据转换成字符
char c =getChar(k);
chars[i] = c;
}
//将有效字符数组反转,即余数倒排列
chars = reverseArray(chars);
//将字符数据转换成字符串
String transAfterdata = arrayToString(chars);
return transAfterdata;
}
/**
* getChar:(将数字转成对应的字符)
*/
public static char getChar(int index){
//防止下标越界
if(index < 0){
System.out.println("你输入的下标不存在!");
return ' ';
}
char[] chars = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
return chars[index];
}
public static char[] reverseArray(char[] chars){
//定义最大下标和最小下标,当最大下标大于最小下标就循环
for (int min =0,max = chars.length -1; min < max ; min++,max--) {
//交换最大下标与最小下标的值
char temp = chars[min];
chars[min] = chars[max];
chars[max] = temp;
}
return chars;
}
public static String arrayToString(char[] chars){
//定义字符串变量
String str = "";
//遍历数组,取出所有的元素与str拼接,再将值赋给str
for (int i = 0; i < chars.length; i++) {
str += chars[i]; // 等价于 str = str +chars[i];
}
return str;
}
}
1.8. 普通查找
public class ArrayUse {
public static void main(String[] args) {
//要查找的数据
int num = 16;
//被查的数组
int arrayInt[] = {34,14,35,90,23,16};
//普通查找
int index = getElementIndex(num,arrayInt);
if(index == -1){
System.out.println(num+"在数组中不存在");
}else{
System.out.println(num+"在数据中下标为:"+index);
}
}
public static int getElementIndex(int num,int arrayInt[]){
//遍历数组,用数组中的每一个元素与我们要查找的元素作比较
for (int i = 0; i < arrayInt.length; i++) {
if(arrayInt[i] == num){
return i; //返回元素对应位置的数组下标
}
}
//不存在查找的元素,返回-1
return -1;
}
}
1.9 二分查找
二分查找的前提是数组中的元素必须是有序的。
二分查找方式一:
public class ArrayUse {
public static void main(String[] args) {
//要查找的数据
int num = 45;
//被查的数组 二分查找数据一定要有序
int arrayInt[] = {3,21,29,34,45,66,78,109};
int index = binaryFindElementIndex1(num,arrayInt);
if(index == -1){
System.out.println(num+"在数组中不存在");
}else{
System.out.println(num+"在数据中下标为:"+index);
}
}
public static int binaryFindElementIndex1(int num,int arrayInt[]){
int min = 0;
int max = arrayInt.length-1;
int mid = (min+max)/2;
//每次判断要查找的数是否与我们数组中的中间的那个数相等
while(num != arrayInt[mid]){
if(num > arrayInt[mid]){
min = mid +1;
mid = (min+max)/2;
}else if(num < arrayInt[mid]){
max = mid -1;
mid = (min+max)/2;
}
if(min > max){
return -1;//不存在查找的元素,返回-1
}
}
return mid;
}
}
二分查找方式二:
public class ArrayUse {
public static void main(String[] args) {
//要查找的数据
int num = 45;
//被查的数组 二分查找数据一定要有序
int arrayInt[] = {3,21,29,34,45,66,78,109};
int index2 = binaryFindElementIndex2(num,arrayInt);
if(index2 == -1){
System.out.println(num+"在数组中不存在");
}else{
System.out.println(num+"在数据中下标为:"+index2);
}
}
public static int binaryFindElementIndex2(int num,int arrayInt[]){
int min = 0;
int max = arrayInt.length-1;
int mid = (min+max)/2;
//判断数据最小下标是否小于最大小标
while(min <= max){
if(num > arrayInt[mid]){
min = mid +1;
mid = (min+max)/2;
}else if(num < arrayInt[mid]){
max = mid -1;
mid = (min+max)/2;
}else if(num == arrayInt[mid]){
return mid;
}
}
//不存在查找的元素,返回-1
return -1;
}
}
2. 数组应用——数组排序
排序算法有很多,包括插入排序,冒泡排序,堆排序,归并排序,选择排序,计数排序,基数排序,桶排序,快速排序等。插入排序,堆排序,选择排序,归并排序和快速排序,冒泡排序都是比较排序,它们通过对数组中的元素进行比较来实现排序,其他排序算法则是利用非比较的其他方法来获得有关输入数组的排序信息。
1.1 选择排序
选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。选择排序是不稳定的排序方法(比如序列[5, 5, 3]第一次就将第一个[5]与[3]交换,导致第一个5挪动到第二个5后面)。
通俗的解释:对比数组中前一个元素跟后一个元素的大小,如果后面的元素比前面的元素小则用一个变量k来记住他的位置,接着第二次比较,前面“后一个元素”现变成了“前一个元素”,继续跟他的“后一个元素”进行比较如果后面的元素比他要小则用变量k记住它在数组中的位置(下标),等到循环结束的时候,我们应该找到了最小的那个数的下标了,然后进行判断,如果这个元素的下标不是第一个元素的下标,就让第一个元素跟他交换一下值,这样就找到整个数组中最小的数了。然后找到数组中第二小的数,让他跟数组中第二个元素交换一下值,以此类推。
稳定性:选择排序是给每个位置选择当前元素最小的,比如给第一个位置选择最小的,在剩余元素里面给第二个元素选择第二小的,依次类推,直到第n-1个元素,第n个元素不用选择了,因为只剩下它一个最大的元素了。那么,在一趟选择,如果一个元素比当前元素小,而该小的元素又出现在一个和当前元素相等的元素后面,那么交换后稳定性就被破坏了。比较拗口,举个例子,序列5 8 5 2 9,我们知道第一遍选择第1个元素5会和2交换,那么原序列中两个5的相对前后顺序就被破坏了,所以选择排序是一个不稳定的排序算法。
public class ArrayUse {
public static void main(String[] args) {
int data[] ={9,2,49,11,35,20,34};
print("选择排序之前:",data); //选择排序之前:9 2 49 11 35 20 34
data = selectSort(data);
print("选择排序之后:",data); //选择排序之后:2 9 11 20 34 35 49
}
private static int[] selectSort(int[] data) {
int min; //定义变量记录每轮比较的最小元素下标
int temp;
for (int i = 0; i < data.length-1; i++) {
min = i;
for (int j = i+1; j < data.length; j++) {
/*
* 对比数组中前一个元素跟后一个元素的大小,如果后面的元素比前面的元素小则用一个变量k来记住他的位置,
* 接着第二次比较,前面“后一个元素”现变成了“前一个元素”,继续跟他的“后一个元素”
* 进行比较如果后面的元素比他要小则用变量min记住它在数组中的位置(下标),
*/
if(data[min] > data[j]){
min = j;
}
}
/*
* 判断最小元素的下标不是第一个元素的下标,就让第一个元素跟他交换一下值
*/
if(min != i){
temp = data[i];
data[i] = data[min];
data[min] = temp;
}
}
return data;
}
public static void print(String message, int[] data){
System.out.print(message);
for (int i = 0; i < data.length; i++) {
System.out.print(data[i]+" ");
}
System.out.println();
}
}
2.2 冒泡排序
冒泡排序算法的运作如下:
1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
2. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
3. 针对所有的元素重复以上的步骤,除了最后一个。
4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
稳定性:冒泡排序就是把小的元素往前调或者把大的元素往后调。比较是相邻的两个元素比较,交换也发生在这两个元素之间。所以,如果两个元素相等,我想你是不会再无聊地把他们俩交换一下的;如果两个相等的元素没有相邻,那么即使通过前面的两两交换把两个相邻起来,这时候也不会交换,所以相同元素的前后顺序并没有改变,所以冒泡排序是一种稳定排序算法。
public class ArrayUse {
public static void main(String[] args) {
int data[] ={9,0,45,11,23,20,-5};
print("冒泡排序之前:",data); //冒泡排序之前:9 0 45 11 23 20 -5
data = BubbleSort(data);
print("冒泡排序之后:",data); //冒泡排序之后:-5 0 9 11 20 23 45
}
private static int[] BubbleSort(int[] data) {
int temp = 0;
for (int i = 0; i < data.length-1; i++) {
for (int j = 0; j < data.length-i-1; j++) {
//如果前一个元素比后一个元素大,交换两个元素的值
if(data[j] > data[j+1]){
temp = data[j];
data[j] = data[j+1];
data[j+1] = temp;
}
}
}
return data;
}
public static void print(String message, int[] data){
System.out.print(message);
for (int i = 0; i < data.length; i++) {
System.out.print(data[i]+" ");
}
System.out.println();
}
}
2.3直接插入排序
每次从无序表中取出第一个元素,把它插入到有序表的合适位置,使有序表仍然有序。
第一趟比较前两个数,然后把第二个数按大小插入到有序表中;第二趟把第三个数据与前两个数从后向前扫描,把第三个数按大小插入到有序表中;依次进行下去,进行了(n-1)趟扫描以后就完成了整个排序过程。
直接插入排序是由两层嵌套循环组成的。外层循环标识并决定待比较的数值。内层循环为待比较数值确定其最终位置。直接插入排序是将待比较的数值与它的前一个数值进行比较,当前一数值比待比较数值大的情况下继续循环比较,直到找到比待比较数值小的并将待比较数值置入其后一位置,结束该次循环。
public class ArrayUse {
public static void main(String[] args) {
int data[] ={5,0,44,1,78,20,111};
print("直接插入排序之前:",data); //直接插入排序之前:5 0 44 1 78 20 111
data = insertSort(data);
print("直接插入排序之后:",data); //直接插入排序之后:0 1 5 20 44 78 111
}
private static int[] insertSort(int[] data) {
int tmp, j = 0;
for (int i = 0; i < data.length; i++) {
tmp = data[i];
j = i - 1;
/*
* 外层循环标识决定待比较的数值。
* 将待比较的数值与它的前一个数值进行比较,
* 当前一数值比待比较数值大的情况下继续循环比较,
* 直到找到比待比较数值小的并将待比较数值置入其后一位置,结束该次循环。
*
*/
while (j >= 0 && tmp < data[j]) {
data[j + 1] = data[j];
j--;
}
data[j + 1] = tmp;
}
return data;
}
public static void print(String message, int[] data){
System.out.print(message);
for (int i = 0; i < data.length; i++) {
System.out.print(data[i]+" ");
}
System.out.println();
}
}