1. 数组元素的拷贝
需求
从指定远数组中复制一个数组,复制从指定的位置开始,到目标数组的指定位置结束。
即:原数组中位置在srcPos到srcPos+length-1之间的元素被分别复制到目标数组中的
destPos到desPos+length-1的位置。
代码实现
/*
srcArr: 原数组
srcPos: 从原数组中的哪一个索引开始拷贝
desArr: 目标数组
desPos: 在目标索引中的哪一个位置开始粘贴
length: 拷贝原数组的元素个数
*/
public static void arrayCopy(int[] srcArr, int srcPos, int[] desArr, int desPos, int length){
if (srcPos < 0 || desPos < 0 || length > srcArr.length )
{
return ;// 不合理
}
for (int i = 0; i < length ;i++ )
{
desArr[desPos+i] = srcArr[srcPos+i] ;
}
}
但是以上代码存在以下问题:
- 只能拷贝int类型数组;
- 代码不够健壮;
因此:
2. 数组元素排序
排序主要有:
1.选择排序(直接选择排序,堆排序);
2. 交换排序(冒泡排序,快速排序);
3. 插入排序(直接插入排序,二分插入排序,Shell排序);
4. 归并排序;
这里主要写了冒泡排序,选择排序,插入排序;但是在开发中因为性能的问题,我们都不会自己写排序算法,不过排序在笔试中经常见到。
2.1 冒泡排序
基本思路:对要未排序的每一个元素从头到尾依次比较相邻的两个元素的大小,若大于则交换位置,经过第一轮的比较得出最大值,然后使用相同的方法把剩下的元素逐个比较即可。
可以看出,若是有N个元素,那么一共要进行N-1轮比较,第M轮要进行 N-M 次比较。(如有6个元素,要进行5轮比较,第一轮比较5次,第二轮比较4次,第三轮比较3次…);
代码实现
// 冒泡排序算法
public class BubbleSort{
public static void main(String args[]){
int[] nums = {6,3,2,5,1};
bubbleSort(nums); // 开始排序
//printArray(nums); // 打印排序后的数组
}
public static void bubbleSort(int[] nums){
for(int i = 0 ; i < nums.length - 1; i++){ // 要比较的轮数
for(int j = 0; j < nums.length - 1 - i; j++){ //每一轮要比较多次数
int temp; //定义临时变量
temp = nums[j];
if (nums[j] > nums[j+1]){
nums[j] = nums[j+1];
nums[j+1] = temp;
}
System.out.print("第"+(i+1)+"轮"+"第"+(j+1)+"次排序结果:");
printArray(nums);
}
}
}
// 按照格式打印数组
public static void printArray(int[] nums){
String res = "[";
for (int i = 0; i < nums.length; i++){
res = res + nums[i];
if ( i != nums.length - 1){
res = res + ",";
}
}
res = res + "]";
System.out.println(res);
}
}
---------- 运行java ----------
第1轮第1次排序结果:[3,6,2,5,1]
第1轮第2次排序结果:[3,2,6,5,1]
第1轮第3次排序结果:[3,2,5,6,1]
第1轮第4次排序结果:[3,2,5,1,6]
第2轮第1次排序结果:[2,3,5,1,6]
第2轮第2次排序结果:[2,3,5,1,6]
第2轮第3次排序结果:[2,3,1,5,6]
第3轮第1次排序结果:[2,3,1,5,6]
第3轮第2次排序结果:[2,1,3,5,6]
第4轮第1次排序结果:[1,2,3,5,6]
输出完成 (耗时 0 秒) - 正常终止
2.1 选择排序
基本思路: 选择某个索引位置的元素,然后和后面的元素一次比较,若大于则交换位置,经过第一轮比较排序得出最小值,然后使用相同的方法把剩下的元素逐个比较即可。可以看出:第一轮会选出最小值,第二轮中会选出第二个最小值,直到最后。
第一轮用arry[0]和后面的元素依次比较,第二轮使用arry[1]和后面的元素相比较,一次类推。N个数进行N-1轮比较。
Java选择排序的思想(以从小到大排序为例,从大到小排序于此相同):
在arr[0]到arr[n-1]中选出最小(大)的的数与arr[0]交换位置,
在arr[1]到arr[n-1]中选出最小(大)的的数与arr[1]交换位置,
在arr[2]到arr[n-1]中选出最小(大)的的数与arr[2]交换位置,
在arr[n-2]到arr[n-1]中选出最小(大)的的数与arr[n-2]交换位置,
…
选择排序每一轮只进行一次交换,相对于冒泡排序效率高一些。
代码实现
class SelectSortDemo
{
public static void main(String[] args)
{
int[] nums = {6,3,2,5,1};
selectSort(nums);
printArray(nums);
}
public static void selectSort(int[] nums){
for(int i=0; i < nums.length-1; i++){ //要比较的轮数
for (int j=0; j < nums.length-i-1; j++ ) //每一轮要交换的次数
{
if (nums[i] > nums[i+j+1] )
{
int temp = nums[i]; // 先把当前索引记录在临时变量中
nums[i] = nums[i+j+1];
nums[i+j+1] = temp;
}
System.out.print("第"+(i+1)+"轮"+"第"+(j+1)+"次排序结果:");
printArray(nums);
}
}
}
// 按照格式打印数组
public static void printArray(int[] nums){
String res = "[";
for (int i = 0; i < nums.length; i++){
res = res + nums[i];
if ( i != nums.length - 1){
res = res + ",";
}
}
res = res + "]";
System.out.println(res);
}
}
---------- 运行java ----------
第1轮第1次排序结果:[3,6,2,5,1]
第1轮第2次排序结果:[2,6,3,5,1]
第1轮第3次排序结果:[2,6,3,5,1]
第1轮第4次排序结果:[1,6,3,5,2]
第2轮第1次排序结果:[1,3,6,5,2]
第2轮第2次排序结果:[1,3,6,5,2]
第2轮第3次排序结果:[1,2,6,5,3]
第3轮第1次排序结果:[1,2,5,6,3]
第3轮第2次排序结果:[1,2,3,6,5]
第4轮第1次排序结果:[1,2,3,5,6]
输出完成 (耗时 0 秒) - 正常终止
选择排序到这里并没有结束!!上述的选择排序的代码其实是有点小瑕疵的。在N轮的排序中,第M轮要进行 N-M 次比较。比如,5个元素的排序,第一轮中需要进行4次位置交换,第二轮进行3次位置交换,效率不够高效!其实,在一轮的排序中,完全可以只进行一次位置的交换!
改进代码
public static void selectSort(int[] nums){
for(int i = 0 ; i < nums.length - 1; i++){ // 要比较的轮数
int minValueIndex = i; // 假设一个最小值的索引
for(int j = 0; j < nums.length - 1 - i; j++){ //每一轮要比较多次数
if (nums[minValueIndex] > nums[i+j+1]){
minValueIndex = i+j+1; // 获取到最小值的索引
}
}
int temp = nums[i]; //定义临时变量
nums[i] = nums[minValueIndex];
nums[minValueIndex] = temp;
System.out.print("第"+(i+1)+"轮排序结果:");
printArray(nums);
}
}
---------- 运行java ----------
第1轮排序结果:[1,3,2,5,6]
第2轮排序结果:[1,2,3,5,6]
第3轮排序结果:[1,2,3,5,6]
第4轮排序结果:[1,2,3,5,6]
输出完成 (耗时 0 秒) - 正常终止
数组元素搜索
数组的搜索:从一个数组中搜索指定元素的索引位置;
搜索的方式:
(1)线性搜索:从头到位 / 从尾到头(indexOf / lastIndexOf)
但是这种搜索方式对于元素个数多的数组性能极低(最少搜索次数为1,最多搜索次数为N,平均搜索次数 (N+1) / 2)。
(2) 二分搜索法(折半查找法/二分搜索法):
代码实现(线性搜索)
// 线性搜索
import java.util.ArrayList;
import java.util.List;
public class LinearSearch{
public static void main(String args[]){
int[] nums = new int[]{6,1,3,3,5,6,9,1};
int ele = 1;
List<Integer> list = linearSearch(nums,ele);
for(int index : list){
System.out.println(index);
}
}
// 线性搜索
public static List<Integer> linearSearch(int[] nums, int ele){
List<Integer> list = new ArrayList<Integer>();
for (int i = 0 ; i < nums.length; i++){
if (nums[i] == ele){
list.add(i);
}
}
return list;
}
}
代码实现(二分查找法)
// 二分查找法的前提:数组必须是有序的!
class BinarySearch
{
public static void main(String[] args)
{
int[] nums = new int[]{4,3,2,5,1,99,22,23,11,21,8,6,9,18,919};
selectSort(nums);
printArray(nums);
int index = binarySearch(nums,99);
if (index == -1) // 判断元素是否存在
{
System.out.println("This element does not exist! ");
}else{
System.out.println(index);
}
}
// 二分查找法
public static int binarySearch(int[] nums, int ele){
int lowIndex = 0;
int highIndex = nums.length-1;
while(lowIndex <= highIndex){
int midIndex = (lowIndex + highIndex) / 2;
if ( ele < nums[midIndex])
{
highIndex = midIndex - 1;
}
else if(ele > nums[midIndex])
{
lowIndex = midIndex + 1;
}
else
{
return midIndex;
}
}
return -1;
}
// 选择排序
public static void selectSort(int[] nums){
for (int i = 0; i < nums.length-1 ; i++)
{
int minValueIndex = i;
for(int j = 0; j < nums.length-1-i; j++){
if (nums[minValueIndex] > nums[i+j+1])
{
minValueIndex = i+j+1;
}
}
int temp = nums[i];
nums[i] = nums[minValueIndex];
nums[minValueIndex] = temp;
}
}
// 打印数组
public static void printArray(int[] nums){
String res = "[";
for (int i = 0; i < nums.length; i++){
res = res + nums[i];
if ( i != nums.length - 1){
res = res + ",";
}
}
res = res + "]";
System.out.println(res);
}
}