常见排序与查找算法
排序
一、交换排序
1.冒泡排序
/**
* 冒泡排序,需要走(nums.length - 1) 趟
* 因为每一趟排序完后,最大值已经在最后面了,无需再排
* 所以每一趟都比上一趟少比较一次,每趟比较(nums.length - 1 - i)次
* @param nums
* @return
*/
public static int[] BUBBLESort(int[] nums){
for (int i = 0; i < nums.length - 1; i++) {
for (int j = 0; j < nums.length - 1 - i; j++) {
if (nums[j+1] < nums[j]){
int temp = nums[j];
nums[j] = nums[j+1];
nums[j+1] = temp;
}
}
}
return nums;
}
2.快速排序
我愿称之为”空位“排序
public static int[] quickSort(int[] nums,int start,int end){
if (start>=end) return nums;
//以起始元素为中间元素
int temp = nums[start];
int i = start;
int j = end;
while (i<j){
//从工作边开始找比中间元素(起始元素)小或等于的元素,如果没找到就继续往左移动,找到了就将"空位"替换
//所谓"空位"就是原先的值已经被赋值到其他位置了,这个位置就是一个“空位”
while (i<j && temp<nums[j]){
j--;
}
nums[i] = nums[j];
//同样再从左边开始
while (i<j && temp>=nums[i]){
i++;
}
nums[j] = nums[i];
}
nums[i] = temp;
//递归调用
quickSort(nums,start,i-1);
quickSort(nums,i+1,end);
return nums;
}
二、插入排序
1.直接插入排序
/**
* 需要走(nums.length - 1)趟,每一趟把第i个值前面的都是一个有序序列(因为每一趟结束后前面的数已经排序好了)
* 定义一个temp用于存储每次第i个位置的值,然后使用while循环来将第i个位置的值放入有序序列中
* 每次从第i个位置的值前一个开始找,如果这个数比temp大就往后挪一位
* @param nums
* @return
*/
public static int[] insertSort(int[] nums){
for (int i = 1; i < nums.length; i++) {
int temp = nums[i];
int j = i - 1;
while (j>=0 && temp < nums[j]){
nums[j+1] = nums[j--];
}
//找到了temp的位置
nums[j+1] = temp;
}
return nums;
}
2.折半插入排序
/*
*折半插入排序法
*/
public static int[] bin_insertSort(int[] nums){
int i,j;
int temp;
for (i=1;i<nums.length;i++){
temp = nums[i];
int low =0;
int high = i-1;
while (low <= high){
int mid = (low+high)/2;
if (temp<nums[mid]){
high = mid-1;
}else {
low = mid+1;
}
}
for (j=i-1;j>=low;j--){
nums[j+1] = nums[j];
}
nums[low] = temp;
}
return nums;
}
3.希尔排序
/**
* 希尔排序(交换法)
* @param nums
* @return
*/
public static int[] shellSort(int[] nums){
for (int gap = nums.length/2; gap >0 ; gap /= 2) {
for (int i = gap; i < nums.length; i++) {
for (int j = i-gap; j >=0 ; j -= gap) {
int temp;
if (nums[j]>nums[j+gap]){
temp = nums[j];
nums[j] = nums[j+gap];
nums[j+gap] = temp;
}
}
}
}
return nums;
}
/**
* 希尔排序(位移法)
* @param nums
* @return
*/
public static int[] shellSort(int[] nums) {
for (int gap = nums.length / 2; gap > 0; gap /= 2) {
for (int i = gap; i < nums.length; i++) {
int j = i;
int temp = nums[j];
if (nums[j] < nums[j - gap]){
while (j - gap >= 0 && nums[j - gap] > temp){
nums[j] = nums[j - gap];
j -= gap;
}
nums[j] = temp;
}
}
}
return nums;
}
三、选择排序
/**
*需要走(nums.length - 1)趟
* 每一趟假设第 i个数为最小值,记录这个值的索引位置为minIndex
* 再从第i+1个数开始找比minIndex索引位置值更小的数,找到了就把这个更小的数的索引值给minIndex
* 最后判断minIndex是否与假设的最小数值索引i不同,不同则把对应位置的值进行交换
* 这样下来每一趟都把最小值放在了前面
* @param nums
* @return
*/
public static int[] selectSort(int[] nums){
for (int i = 0; i < nums.length - 1; i++) {
int minIndex = i;
for (int j = i+1; j < nums.length; j++) {
//找出最小数的索引
if (nums[j]<nums[minIndex]) minIndex = j;
}
//若最小值索引发生变化就进行交换
if (minIndex!=i){
int temp = nums[i];
nums[i] = nums[minIndex];
nums[minIndex] = temp;
}
}
return nums;
}
四、归并排序
public static void mergeSort(int[] nums, int left, int right, int[] temp) {
if (left<right){
int mid = (left + right)/2;
mergeSort(nums,left,mid,temp);
mergeSort(nums,mid+1,right,temp);
merge(nums,left,right,mid,temp);
}
}
public static void merge(int[] nums, int left, int right, int mid, int[] temp) {
int i = left;
int j = mid + 1;
int t = 0;
while (i <= mid && j <= right) {
if (nums[i] < nums[j]) {
temp[t++] = nums[i++];
}
if (nums[i] > nums[j]) {
temp[t++] = nums[j++];
}
while (i <= mid && j > right) {
temp[t++] = nums[i++];
}
while (i > mid && j <= right) {
temp[t++] = nums[j++];
}
}
t=0;
int tempLeft = left;
while (tempLeft<=right) {
nums[tempLeft++] = temp[t++];
}
}
五、基数排序
/**
* 先计算出最大数的位数决定需要循环走的趟数
* 通过定义10个桶分别存放按0~9大小存放 个位、十位/...等
* 每按一次位上数大小排序后将依次将桶里的数覆盖原数组的值
* @param nums
* @return
*/
public static int[] baseSort(int[] nums) {
//计算最大数
int max = nums[0];
for (int i = 0; i < nums.length; i++) {
if (nums[i] > max) {
max = nums[i];
}
}
//计算出最大位数
int maxLength = (max + "").length();
int[][] buckets = new int[10][nums.length];
int[] posElem = new int[10];
for (int i = 0, n = 1; i < maxLength; i++, n *= 10) {
for (int j = 0; j < nums.length; j++) {
int posNum = nums[j] / n % 10;
buckets[posNum][posElem[posNum]++] = nums[j];
}
int index = 0;
for (int k = 0; k < buckets.length; k++) {
if (posElem[k] != 0) {
for (int l = 0; l < posElem[k]; l++) {
nums[index++] = buckets[k][l];
}
}
posElem[k] = 0;
}
}
return nums;
}
查找
一、二分查找
/**
* 每次取中间值(low + high)/2与查询值比较
* 若查询值大于中间值说明查询值在左边,将high值置于mid - 1,重写计算mid
* 若查询值小于中间值说明查询值在右边,将low值置于mid + 1,重写计算mid
* 若相等则直接返回对应下标
* 当low>high时说明没有查找到对应的值
* @param nums
* @param searchVal
* @return
*/
public static int binarySearch(int[] nums, int searchVal) {
int low = 0;
int high = nums.length - 1;
int mid;
while (low <= high) {
mid = (low + high) / 2;
if (searchVal > nums[mid]) {
low = mid + 1;
} else if (searchVal < nums[mid]) {
high = mid - 1;
} else {
return mid;
}
}
return -1;
}

浙公网安备 33010602011771号