1、冒泡排序(Bubble Sort)
算法描述:
(1)比较相邻的元素。如果第一个比第二个大,就交换它们两个;
(2)对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;
(3)针对所有的元素重复以上的步骤,除了最后一个;
(4)重复步骤1~3,直到排序完成。
如果两个元素相等,不会再交换位置,所以冒泡排序是一种稳定排序算法。
方法一:自定义数组实现冒泡排序
package BubbleSort;
public class BubbleSort {
public static void bubbleSort(int [] data){
int arrayLength = data.length;
for (int i=1;i<arrayLength;i++){//从第i次排序
for (int j=0;j<arrayLength-i;j++){ //从索引为j的位置开始
if(data[j]>data[j+1]){//相邻的两个元素比较大小
int temp = data[j+1];//定义一个临时变量,用来交换两个元素
data[j+1]=data[j];
data[j]=temp;
}
}
System.out.println("第"+i+"次排序:\n"+java.util.Arrays.toString(data));
}
}
public static void main (String[] args){
int[] data ={1,5,7,9,2,5,3,4,6,8};
System.out.println("排序之前的序列为:\n"+java.util.Arrays.toString(data));
bubbleSort(data); //调用方法
System.out.println("排序之后的序列为:\n"+java.util.Arrays.toString(data));
}
}
方法二:接收键盘输入的数据,实现冒泡排序
package BubbleSort;
import java.util.Scanner;
public class BubbleSort02 {
public static void bubbleSort(int[] data){
int arrayLength = data.length;
for (int i=1;i<arrayLength;i++){//从第i次排序
for (int j=0;j<arrayLength-i;j++){ //从索引为j的位置开始
if(data[j]>data[j+1]){//相邻的两个元素比较大小
int temp = data[j+1];//定义一个临时变量,用来交换两个元素
data[j+1]=data[j];
data[j]=temp;
}
}
System.out.println("第"+i+"次排序:\n"+java.util.Arrays.toString(data));
}
}
public static void main(String args[]){
Scanner sc = new Scanner(System.in);
String str = sc.next();
String[] data = str.split(",");
int[] array = new int[data.length];
for(int i = 0;i<array.length;i++){
array[i] = Integer.parseInt(data[i]);
}
System.out.println("排序之前的序列为:\n"+java.util.Arrays.toString(array));
bubbleSort(array); //调用方法
System.out.println("排序之后的序列为:\n"+java.util.Arrays.toString(array));
}
}
2、快速排序(Quick Sort)
算法描述:
使用分治法来把一个串(list)分为两个子串(sub-lists)。具体算法描述如下:
(1)从数列中挑出一个元素,称为“基准”(pivot);
(2)重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
(3)递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
key值的选取可以有多种形式,例如中间数或者随机数,分别会对算法的复杂度产生不同的影响。
方法一:自定义数组实现快速排序
package QuickSort;
public class QuickSort {
public static void quickSort(int[] data, int low, int high){
int i,j,temp,t;
if(low>high){
return;
}
i=low;
j=high;
//temp就是基准位
temp = data[low];
System.out.println("基准位:"+temp);
while (i<j) {
//先看右边,依次往左递减
while (temp<= data[j]&&i<j) {
j--;
}
//再看左边,依次往右递增
while (temp>= data[i]&&i<j) {
i++;
}
//如果满足条件则交换
if (i<j) {
t = data[j];
data[j] = data[i];
data[i] = t;
}
}
//最后将基准为与i和j相等位置的数字交换
data[low] = data[i];
data[i] = temp;
//递归调用左半数组
quickSort(data, low, j-1);
//递归调用右半数组
quickSort(data, j+1, high);
}
public static void main(String[] args){
int[] array = {1,9,5,3,7,52,32,41,23,15,81,90,19};
System.out.println("排序之前的序列为:\n"+java.util.Arrays.toString(array));
quickSort(array, 0, array.length-1);
System.out.println("排序之后的序列为:\n"+java.util.Arrays.toString(array));
}
}
方法二:接收键盘输入的数据,实现快速排序
package QuickSort;
import java.util.Scanner;
public class QuickSort02 {
public static void quickSort(int[] data, int low, int high){
int i,j,temp,t;
if(low>high){
return;
}
i=low;
j=high;
//temp就是基准位
temp = data[low];
System.out.println("基准位:"+temp);
while (i<j) {
//先看右边,依次往左递减
while (temp<= data[j]&&i<j) {
j--;
}
//再看左边,依次往右递增
while (temp>= data[i]&&i<j) {
i++;
}
//如果满足条件则交换
if (i<j) {
t = data[j];
data[j] = data[i];
data[i] = t;
}
}
//最后将基准为与i和j相等位置的数字交换
data[low] = data[i];
data[i] = temp;
//递归调用左半数组
quickSort(data, low, j-1);
//递归调用右半数组
quickSort(data, j+1, high);
}
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
String str = sc.next();
String[] data = str.split(",");
int[] array = new int[data.length];
for(int i = 0;i<array.length;i++){
array[i] = Integer.parseInt(data[i]);
}
System.out.println("排序之前的序列为:\n"+java.util.Arrays.toString(array));
quickSort(array, 0, array.length-1);
System.out.println("排序之后的序列为:\n"+java.util.Arrays.toString(array));
}
}
3、归并排序(Merge Sort)
算法描述:
(1)把长度为n的输入序列分成两个长度为n/2的子序列。
(2)对这两个子序列分别采用归并排序。
(3)将两个排序好的子序列合并成一个最终的排序序列。
3.1归并排序的流程
3.2合并两个有序数组的流程
3.3代码
方法一:自定义数组实现数组合并
package MergeSort;
import java.util.SortedMap;
public class MergeSort {
public static void mergeSort(int[] data){
sort(data,0,data.length-1);
}
public static void sort(int[] arr, int left,int right){
if(left == right){
return;
}
int mid = left + ((right-left)>>1);
sort(arr,left,mid);
sort(arr,mid+1,right);
merge(arr,left,mid,right);
}
private static void merge(int[] arr, int left, int mid, int right) {
int[] temp = new int[right-left+1];
int i=0;
int p1=left;
int p2=mid+1;
//比较左右两部分的元素,哪个小,把那个元素填入temp中
while (p1<=mid&&p2<=right){
temp[i++]=arr[p1]<arr[p2] ? arr[p1++] : arr[p2++];
}
//上面的循环退出后,把剩余的元素依次填入到temp中
//以下两个while只有一个会执行
while(p1<=mid){
temp[i++] = arr[p1++];
}
while (p2<=right){
temp[i++] = arr[p2++];
}
//把最终的排序的结果复制给原数组
for(i=0;i<temp.length;i++){
arr[left+i]=temp[i];
}
}
public static void main(String[] args) {
int[] data={3,44,38,5,47,15,36,26,27,2,46,4,19,50,48};
System.out.println("排序之前的序列为:\n"+java.util.Arrays.toString(data));
mergeSort(data);
System.out.println("排序之后的序列为:\n"+java.util.Arrays.toString(data));
}
}
方法二:接收键盘输入的数据,实现数组合并
package MergeSort;
import java.util.Scanner;
public class MergeSort02 {
public static void mergeSort(int[] data){
sort(data,0,data.length-1);
}
public static void sort(int[] arr, int left,int right){
if(left == right){
return;
}
int mid = left + ((right-left)>>1);
sort(arr,left,mid);
sort(arr,mid+1,right);
merge(arr,left,mid,right);
}
private static void merge(int[] arr, int left, int mid, int right) {
int[] temp = new int[right-left+1];
int i=0;
int p1=left;
int p2=mid+1;
//比较左右两部分的元素,哪个小,把那个元素填入temp中
while (p1<=mid&&p2<=right){
temp[i++]=arr[p1]<arr[p2] ? arr[p1++] : arr[p2++];
}
//上面的循环退出后,把剩余的元素依次填入到temp中
//以下两个while只有一个会执行
while(p1<=mid){
temp[i++] = arr[p1++];
}
while (p2<=right){
temp[i++] = arr[p2++];
}
//把最终的排序的结果复制给原数组
for(i=0;i<temp.length;i++){
arr[left+i]=temp[i];
}
}
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
String str = sc.next();
String[] data = str.split(",");
int[] array = new int[data.length];
for(int i = 0;i<array.length;i++){
array[i] = Integer.parseInt(data[i]);
}
System.out.println("排序之前的序列为:\n"+java.util.Arrays.toString(array));
mergeSort(array);
System.out.println("排序之后的序列为:\n"+java.util.Arrays.toString(array));
}
}
4、二分查找(Binary Search)
算法描述:
(1)二分查找也称折半查找,它是一种效率较高的查找方法,要求列表中的元素首先要进行有序排列。
(2)首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;
(3)否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。
(4)重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。
代码:
方法一:递归实现二分查找
package BinarySearch;
public class BinarySearch {
/**
*二分查找时间复杂度0(1og2n);空间复杂度0(1)
*
*@param arr被查找的数组
*@param left
*@param right
*@param findVal
*@return 返回元素的索引
*/
public static int binarySearch(int[] arr ,int left,int right,int findVal){
if (left > right){ //递归退出条件,找不到,返回-1
return -1;
}
int midIndex = (left+right)/2;
if(findVal < arr[midIndex]){ //从右边向左边递归查找
return binarySearch(arr,left,midIndex,findVal);
} else if (findVal > arr[midIndex]){ //从左边向右边递归查找
return binarySearch(arr,midIndex,right,findVal);
} else{
return midIndex;
}
}
public static void main(String[] args) {
//数组需要是已经排序好的,二分查找主要使用在已经排序好的数组
int[] data ={-23,-20,-17,8,12,23,40,50};
int i = binarySearch(data,0,data.length,12);
i++;
System.out.println("查找到的数据位于第"+i+"个位置");
}
}
方法二:非递归实现二分查找
package BinarySearch;
public class BinarySearch02 {
/**
* 非递归的二分查找
*title:commonBinarySearch
*@param arr
*@param key
*@return 关键字位置
*/
public static int commonBinarySearch(int[] arr,int key){
int low = 0;
int high = arr.length - 1;
int middle = 0; //定义middle
if(key < arr[low] || key > arr[high] || low > high){
return -1;
}
while(low <= high){
middle = (low + high) / 2;
if(arr[middle] > key){
//比关键字大则关键字在左区域
high = middle - 1;
}else if(arr[middle] < key){
//比关键字小则关键字在右区域
low = middle + 1;
}else{
return middle;
}
}
return -1; //最后仍然没有找到,则返回-1
}
public static void main(String[] args) {
//数组需要是已经排序好的,二分查找主要使用在已经排序好的数组
int[] data ={-23,-20,-17,8,12,23,40,50};
int i = commonBinarySearch(data,12);
i++;
System.out.println("查找到的数据位于第"+i+"个位置");
}
}
拓展需求:
当一个有序数组中,有多个相同的数值时,如何将所有的数值都查找到。
代码:
package BinarySearch;
import java.util.ArrayList;
public class BinarySearch03 {
public static void main(String[] args) {
int[] arr={10,20,23,26,26,2629,31,35,36};
ArrayList list = binarySearch4(arr, 0, arr.length - 1, 26);
System.out.println("返回值下标为:" + list);
}
//当一个有序数组中,有多个相同的数值时,如何将所有的数值都查找到,比如这里的 1000.
public static ArrayList binarySearch4(int[] arr, int left, int right, int findVal){
if(left > right){ //left > right 说明递归整个数组还没有找到
return new ArrayList<Integer>();
}
int mid = (left + right)/2;
int midValue = arr[mid];
if(findVal > midValue){//向右递归
return binarySearch4(arr,mid+1,right,findVal);
}else if( findVal < midValue){//向左递归
return binarySearch4(arr,mid,mid-1,findVal);
}else {
/*思路分析:
1.在找到mid时,不马上返回
2.向mid索引值的左边扫描,将所有满足 1000的元素的下标,加入到集合ArrayList中
3.向mid索引值的右边扫描,将所有满足 1000的元素的下标,加入到集合ArrayList中
4.返回ArrayList集合*/
ArrayList<Integer> list = new ArrayList<Integer>();
//向mid索引值的左边扫描,将所有满足 1000的元素的下标,加入到集合ArrayList中
int temp = mid -1;
while(true){
if(temp < 0 || arr[temp] != findVal){
break;
}
list.add(temp);
temp -= 1;//左移
}
list.add(mid);
//向mid索引值的右边扫描,将所有满足 1000的元素的下标,加入到集合ArrayList中
temp = mid + 1;
while(true){
if(temp >= arr.length || arr[temp] != findVal){
break;
}
list.add(temp);
temp += 1;//右移
}
return list;
}
}
}