在Java开发中有这样两个常见任务,一种即在某一组中查找某个特定的元素,另一种即是将某一组元素按照特定的顺序排序。完成这些任务可以使用多种算法,而这些算法间存在一定的差异,接下来我们探究一下这些算法。
一、查找
1.1、线性查找法
线性查找就是通过索引对数组data的每个元素进行遍历,如果发现要找的目标元素和数组data中的某个元素相同时,就返回已经查找到,当然,我们也是可以改进一下,就是直接把找到的元素返回即可。
public static <T extends Comparable<? super T>>
boolean linearSearch(T[] data, int min , it max, T target)
{
int index = min;
boolean found = false;
while(!found && index <= max){//判断界限
if(data[index].compareTo(target) == 0){
found = true;
}
index++;
}
return found;
}
1.2、二分查找法
二分查找法的效率比线性搜索法高,因为不用全部遍历一遍,节省了很多的时间,这里我们采用的方法是递归调用来进行查找的,如果发现中点位置的元素大小小于目标元素,就将中点位置的索引+1,进行递归调用,如果大于目标元素,就将中点位置索引-1,进行递归调用,而递归的出口就是,当中点位置的值和目标元素的值相等时,则返回结果。
public static <T extends Comparable<? super T>>
boolean binarySearch(T[] data, int min , it max, T target)
{
boolean found = false;
int midpoint = (min+max)/2;//选择中点位置
if(data[midpoint].compareTo(target) == 0){
found = true;
} else if(data[midpoint].compareTo(target) > 0){
if(min <= midpoint - 1){
found = binarySearch(data, min, midpoint - 1, target);
}
} else if(data[midpoint].compareTo(target) > 0){
if(max >= midpoint + 1){
found = binarySearch(data, min, midpoint + 1, target);
}
}
二、排序
排序分为
顺序排序:选择,插入,冒泡排序;
对数排序:快速,归并排序;
2.1、选择排序
通过扫描整个列表找出最小值,将这个值与该列表的第一个位置的值交换。扫描剩余(除了第一个值)部分列表并找出最小值,然后将它和该列表的第二个位置处的值交换。以此类推下去。
public static <T extends Comparable<? super T>>
void selectionSort(T[] data){
int min ;//定义存储扫描的最小值
T temp;
for(itn index = 0; index < data.length - 1; index++){
min = index;//初始化为最小值为第一个
for(int scan = index + 1; scan < data.length - 1; scan++){
if(data[scan].compareTo(data[min]) < 0){//如果小于最小值,就将找到的最小值赋值给当前的最小值
min = scan;
}
}
//将找到的最小值和当前的第一个位置交换
temp = data[min];
data[min] = data[index];
data[index] = temp;
}
}
2.2、插入排序
插入排序算法通过反复的将某个特定的值插入到该列表某个已排序的子集中来完成对列表值得排序。
策略:将列表中的头两个值依据其相对大小对其进行排序,将列表的第三个值插入到头两个已排序的值中的恰当位置,然后将第四个值插入到前三个已排序的恰当位置。
public static <T extends Comparable<? super T>>
void selectionSort(T[] data){
for(int index = 1; index < data.length; index++){
T key = data[index];//将这个元素暂时保存
int position = index;//外层循环保存索引
//查找更大的元素到对的位置
while(position > 0 && data[position - 1].compareTo(key) > 0){
data[position] = data[position - 1];
position --;
}
data[position] = key;
}
}
2.3、冒泡排序
重复的比较列表中的相邻的元素,如果发现某个相邻的元素的位置不对的时候,就将这两个元素的位置交换。
public static <T extends Comparable<? super T>>
void selectionSort(T[] data){
int position ,scan;
T temp;
for(position = data.length - 1; position >=0; position --){
for(scan = 0; scan <= position - 1; scan++){
if(data[scan].compareTo(data[scan+1]) > 0){
swap(data,scan, scan + 1);
}
}
}
}
2.4、快速排序
通过任意选定的分区元素将该列表分区,然后对分区元素的任一边的子列表进行递归排序。
public static <T extends Comparable<T>> void quickSort(T[] data){
quickSort(data, 0, data.length-1);
}
public static <T extends Comparable<T>> void quickSort(T[] data, min , max){
if(min < max){
//创建分区索引
int indexOfPartition = partition(data, min, max);
//对左分区进行递归排序
quickSort(data, min, indexOfPartition -1);
//对右分区进行递归排序
quickSort(data, indexOfPartition + 1, max);
}
}
public static <T extends Comparable<T>> void partition(T[] data, int min , int max){
T partitionelement;
int left, right;
int middle = (min+max)/2;
//使用中间数据值作为分区元素
partitionelement = data[middle];
//将第一个元素和分区元素交换位置
swap(data,middle,min);
left = min;
right = max;
while(left < right){
//如果左边的元素比分区元素小就索引右移查找下一个
while(left< right && data[left].compareTo(partitionelement) <= 0){
left ++;
}
//如果右边元素比分区元素大就索引左移查找下一个元素
while(data[right].compareTo(partitionelement) > 0){
right ++;
}
if(left < right){
swap(data,left,right);
}
}
//将分区元素放回到原来的位置
swap(data, min, right);
return right;
}
2.5、归并排序
将列表分成大约相等的两个部分,然后对每一部分列表递归调用其本身,继续该列表的递归分解,直至达到该递归的基本情形,这是列表被分割成长度为1的列表,根据定义,此时已排序好。
private static <T extends Comparable<T>> void mergeSort(T[] data, int min , int max){
if(min < max){
int mid = (min+max)/2;
mergeSort(data,min,mid);
mergeSort(data,mid+1,max);
merge(data,min,mid,max);
}
}
private static <T extends Comparable<T>> void merge(T[] data, int first , int mid, int last){
T[] temp = (T[])(new Comparable[data.length]);
int first1 = first, last1 = mid;
int first2 = mid+1, last2 = last;
int index = first1;
//复制每一个子序列中的更小的元素到temp数组中,直到已排序好
while(first1 <= last1 && first2 <= last2){
if(data[first1].compareTo(data[first2]) < 0){
temp[index] = data[first1];
first1++;
} else {
temp[index] = data[first2];
first2++;
}
index++;
}
//从第一个子序列中复制剩余的元素到temp数组中
while(first1 <= last1){
temp[index] = data[first1];
first1++;
index++;
}
//从第二个子序列中复制剩余的元素到temp数组中
while(first2 <= last2){
temp[index] = data[first2];
first2++;
index++;
}
//复制归并数据temp到原始的序列中
for(index = first; index <= last; index++){
data[index] = temp[index];
}
}