1、基本查找
public class test {
public static void main(String[] args) {
//定义一个数组
int[] array = {1,5,8,9,5,21,53,90,10,2};
//根据元素找出该元素在数组中第一次出现的索引
int index = getIndexByEle(array,5);
System.out.println("该元素的索引为:"+index);
}
private static int getIndexByEle(int[] array,int ele) {
for (int i = 0; i < array.length; i++) {
if (ele == array[i])
return i;
}
return -1;//没有找到该元素
}
}
2、二分查找
前提:该数组的元素必须有序
思想:每一次都查找中间的元素,比较大小就能够减少查找一半的元素
代码实现:
private static int getIndexByEle(int[] arr, int ele) {
//定义最小索引,中间索引,最大索引
int minIndex = 0;
int maxIndex = arr.length-1;
int midIndex = (minIndex+maxIndex)/2;
while (minIndex <= maxIndex){
//查找元素正好等于中间索引元素
if (ele == arr[midIndex])
return midIndex;
//查找元素小于中间索引元素
else if (ele < arr[midIndex])
maxIndex = midIndex-1;
//查找元素大于中间索引元素
else
minIndex = midIndex+1;
midIndex = (minIndex+maxIndex)/2;
}
return -1;//没有找到
}
3、冒泡排序
原理:数组元素两两比较,交换位置,大元素往后放,那么经过一轮的比较后,最大的元素,就会出现在最大索引处。
代码实现:
//冒泡排序
private static int[] sortArray(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
int flag = 0;
//将最大元素后调至该次循环的最大索引处
for (int j = 0; j < arr.length - i - 1; j++) {
if (arr[j] > arr[j+1]){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
flag = 1;
}
}
if (flag == 0)//如果当前已经有序,则跳出循环
break;
}
return arr;
}
4、选择排序
原理:从0索引处开始,依次和后面的元素进行比较,小的元素往前放,经过一轮比较后,最小的元素就出现在了最小索引处
代码实现:
//选择排序
private static int[] sortArray(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
for (int j = i+1; j < arr.length; j++) {
if (arr[i] > arr[j]){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
return arr;
}
5、直接插入排序
原理:其基本操作是将一个记录插入到一个长度为m的有序表中,使之有序。从1索引处开始,将后面的元素,插入到之前的有序列表中使之仍保持有序
代码实现:
//直接插入排序
private static int[] sortArray(int[] arr) {
for (int i = 1; i < arr.length; i++) {
int j = i;
while (j > 0 && arr[j] < arr[j-1]){
int temp = arr[j];
arr[j] = arr[j-1];
arr[j-1] = temp;
j--;
}
}
return arr;
}
//两层for循环
private static int[] sortArray1(int[] arr) {
for (int i = 1; i < arr.length; i++) {
for (int j = i; j > 0; j--) {
if (arr[j] < arr[j - 1]) {
int temp = arr[j];
arr[j] = arr[j - 1];
arr[j - 1] = temp;
}
}
}
return arr;
}
6、希尔排序(又称缩小增量排序)
思想:先将原表按增量ht分组,每个子文件按照直接插入排序法排序。同样,用下一个增量ht/2将文件再分为子文件,再直接插入法排序。直到ht=1时整个文件排好序。
关键:选择合适的增量,增量的最普通选择就是使用数组长度的一半
排序算法:可以通过三重for循环来实现
代码实现:
//希尔排序
private static int[] sortArray(int[] arr) {
for (int h = arr.length/2; h > 0; h /= 2) {
for (int i = h; i < arr.length; i++) {
int j = i;
while (j-h >= 0 && arr[j] < arr[j - h]) {
int temp = arr[j];
arr[j] = arr[j - h];
arr[j - h] = temp;
j -= h;
}
}
}
return arr;
}
增量的选取选择克努特序列:h=1; h=3*h+1;
//根据克努特序列,选择增量
private static int[] sortArray1(int[] arr) {
int ht = 1;
while (ht <= arr.length/3)
ht = ht*3+1;
for (int h = ht; h > 0; h =(h-1)/3) {
for (int i = h; i < arr.length; i++) {
int j = i;
while (j-h >= 0 && arr[j] < arr[j - h]) {
int temp = arr[j];
arr[j] = arr[j - h];
arr[j - h] = temp;
j -= h;
}
}
}
return arr;
}
7、快速排序
思想:分治法,比大小,再分区
首先,从数组中取出一个数,作为基准数
然后,分区:将比这个数大或是等于的数全部放到它的右边,小于它的数全部放到它的左边
最后,再对左右区间重复第二步,直到各个区间只有一个数
代码实现:
public class ArrayTest6 {
public static void main(String[] args) {
int[] arr = {24, 69, 80, 52, 13};
quickSort(arr,0, arr.length-1);
for (int i : arr) {
System.out.println(i);
}
}
//快速排序,传入数组,开始位置,结束位置
private static void quickSort(int[] arr,int low,int high) {
// 找寻基准数据的正确索引
if (low < high){
int index = getIndex(arr,low,high);
quickSort(arr,low,index-1);
quickSort(arr,index+1,high);
}
}
private static int getIndex(int[] arr, int low, int high) {
int tmp = arr[low];
while (low < high){
while (low < high && arr[high] >= tmp)
high--;
arr[low] = arr[high];
while (low < high && arr[low] < tmp)
low++;
arr[high] = arr[low];
}
// 跳出循环时low和high相等,此时的low或high就是tmp的正确索引位置
arr[low] = tmp;
return low;//返回tmp的正确位置
}
}
8、归并排序
思想:利用归并的思想实现排序的方法
二路归并排序:假设初始序列有N个记录,则可以看作是N个有序的子序列,每个子序列的长度为1,然后两两归并,得到N/2个长度为2或1的子序列,再两两归并…如此重复,直至得到一个长度为N的有序序列为止。
代码实现:
public class ArrayTest7 {
public static void main(String[] args) {
int[] arr = {24, 69, 80, 52, 13};
mergeSort(arr,0, arr.length-1);
for (int i : arr) {
System.out.println(i);
}
}
//归并排序
private static void mergeSort(int[] arr,int low,int high) {
// 找寻基准数据的正确索引
if (low < high){
int mid = (low+high)/2;
mergeSort(arr,low,mid);//将左边进行归并排序
mergeSort(arr,mid+1,high);//将右边进行归并排序
merge(arr,low,mid,high);//将两个有序数组进行归并
}
}
//将两个有序数组进行归并
private static void merge(int[] arr, int low, int mid, int high) {
int i = low;
int j = mid+1;
int[] tempArr = new int[high-low+1];//定义临时数组
int index = 0;//临时数组的起始索引
while (i <= mid && j <= high){
if (arr[i] <= arr[j])
tempArr[index++] = arr[i++];
else
tempArr[index++] = arr[j++];
}
//将左边剩余元素填充进temp中
while (i <= mid)
tempArr[index++] = arr[i++];
//将右边剩余元素填充进temp中
while (j <= high)
tempArr[index++] = arr[j++];
//将临时数组中的元素放到原数组中去
for (int k = 0; k < tempArr.length; k++) {
arr[low+k] = tempArr[k];
}
}
}
9、基数排序(桶排序)
思想:它不需要直接对元素进行相互比较,也不需要将元素相互交换,需要做的就是对元素进行“分类”。基数排序的实现不需要进行对关键字的比较,只需对关键字进行“分配“与”收集“两种操作即可完成。
按个位十位百位的数字分别进行分配与收集的操作。
代码实现:
//基数排序
private static void sortArray(int[] arr) {
//首先得到最大数的长度
int max = arr[0];
for (int i = 1; i < arr.length; i++) {
if (arr[i] > max)
max = arr[i];
}
int len = String.valueOf(max).length();
//定义二维数组,放十个桶
int[][] tempArr = new int[10][arr.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 ys = (arr[j] / n) % 10;
// 把数据放在指定数组中,有两个信息,放在第几个桶+数据应该放在第几位
tempArr[ys][counts[ys]++] = arr[j];
}
//记录取的数字应该放到的位置
int index = 0;
for (int j = 0; j < counts.length; j++) {
for (int k = 0; k < counts[j]; k++) {
arr[index++] = tempArr[j][k];
}
//清除上一次统计的个数
counts[j] = 0;
}
}
}
10、堆排序
堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序。
思想:将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点;将其与末尾元素进行交换,此时末尾元素就是最大值;然后将剩余n-1个元素重新构造呈一个堆,这样会得到n个元素的次小值;如此反复执行,便能得到一个有序序列了;
排序步骤:首先建造成一颗完全二叉树,然后从最后一个非叶子结点开始转成大顶堆;把根节点的元素和最后一个元素进行调换;
代码实现:
//堆排序
private static void sortArray(int[] arr) {
//1.构建大顶堆
for (int i = arr.length/2-1; i >= 0 ; i--) {
//从第一个非叶子结点从下至上,从左至右调整结构
adjustHeap(arr,i, arr.length);
}
//2.调整堆结构+交换堆顶元素与末尾元素
for (int i = arr.length-1; i > 0; i--) {
//将堆顶元素与末尾元素进行交换
int temp=arr[0];
arr[0] = arr[i];
arr[i] = temp;
//重新对堆进行调整
adjustHeap(arr,0,i);
}
}
private static void adjustHeap(int[] arr, int i, int length) {
int temp = arr[i];
//从i结点的左子节点开始,也就是2i+1处开始
for (int j = 2*i+1; j < length; j = j*2+1) {
//如果左子结点小于右子结点,j指向右子结点
if (j+1 < length && arr[j] < arr[j+1])
j++;
//如果子结点大于父结点,将子结点的值赋给父结点(不用进行交换)
if(arr[j] > temp){
arr[i] = arr[j];
i = j;
}else{
break;
}
}
arr[i] = temp;//将temp的值放到最终位置
}