冒泡排序
基本思想:将待排序序列从前向后一次排列元素, 若发现逆序则交换,使较大的元素相后移动。
优化:若交换一轮下来发现没有进行交换,这说明有序,这设立一个flag进行判断,减少不必要的比较。
public class BubbleSort {
public static void bubbleSort(int[] arr){
int temp =0;//临时变量
boolean flag = false;//标识变量
for (int i = 0; i <arr.length ; i++) {
for (int j = 0; j <arr.length - 1 ; j++) {
//如果前面的数比后面的大交换
if (arr[j]>arr[j+1]){
flag = true;
temp = arr[i];
arr[j] = arr[j +1];
arr[j + 1] = temp;
}
}
if (!flag){
break;//一次也没发生交换
}else {
flag = false;
}
}
}
public static void main(String[] args) {
//测试冒泡的速度
//创建10000个随机数组
int[] arr =new int[80000];
for (int i = 0; i < 80000; i++) {
//生成一个【0,1000000】
arr[i] = (int) (Math.random()* 8000000);
}
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String format = simpleDateFormat.format(date);
System.out.println("排序之前的时间是="+format);
//测试冒泡
bubbleSort(arr);
Date date2 = new Date();
String format2 = simpleDateFormat.format(date2);
System.out.println("排序之hou的时间是="+format2);
}
}
插入排序
基本思想:把数列的元素看成一个有序和无序表;开始时有序表是1,无序表是n-1个元素;开始排序时每次从无序表取一个元素将他的排列码与有序表进行比较,从而插入到到适当位置
public class InsertSort {
public static void main(String[] args) {
//创建要给80000个的随机数组
int[] arr = new int[80000];
for (int i = 0; i < 80000; i++) {
arr[i] = (int) (Math.random() * 8000000);//生成一个【0,8000000】
}
System.out.println("排序前");
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String format = simpleDateFormat.format(date);
System.out.println("排序前的时间是="+format);
insertSort(arr);
Date date1 = new Date();
String format1 = simpleDateFormat.format(date1);
System.out.println("排序后的时间是="+format1);
}
public static void insertSort(int[] arr){
int insertVal =0;
int insertIndex = 0;
for (int i = 0; i <arr.length ; i++) {
//定义待插入的数
insertVal = arr[i];
insertIndex = i - 1; //即arr[1] 的前面这个数的下标
//insertVal 找到插入位置
while (insertIndex >= 0 && insertVal < arr[insertIndex]){
arr[insertIndex + 1] = arr[insertIndex];
insertIndex--;
}
//当退出while循环时 说明插入的位置找到 insertIndex + 1
//举例:
//判断是否需要赋值
if (insertIndex + 1!=i) {
arr[insertIndex + 1] = insertVal;
}
}
}
}
二分查找
基本思路:确定数组的中间下标,如果将要查找的数大于mid,说明要查找的数在右边这向右递归,小于反之;找到即结束递归,若递归完仍然没有也要结束,左边小于右边;
// 注意 使用二分查找 的前提是 该数组有序
public class BinarySearch {
public static void main(String[] args) {
int arr[] = {1,3,4,5,6,7,8};
int resIndexList = binarySearch(arr,0,arr.length - 1,1);
System.out.println(resIndexList);
}
public static int binarySearch(int[] arr,int left,int right,int findVal){
//当left> right 时 说明递归整个数组 但没有找到
if (left > right){
return -1;
}
int mid = (left + right) /2;
int minValue =arr[mid];
if (findVal > minValue){
//向右递归
return binarySearch(arr, mid + 1, right, findVal);
}else if (findVal <minValue){
return binarySearch(arr, left, mid-1, findVal);
}else {
return mid;
}
}
}
//这里没有考虑多个重复值的情况
归并排序
基本思想:分而治之
public class MergeSort {
public static void main(String[] args) {
//创建要给80000个的随机数组
int[] arr = new int[8000000];
for (int i = 0; i < 8000000; i++) {
arr[i] = (int) (Math.random() * 8000000);//生成一个【0,8000000】
}
System.out.println("排序前");
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String format = simpleDateFormat.format(date);
System.out.println("排序前的时间是=" + format);
int temp[] = new int[arr.length]; //归并排序需要一个额外空间
mergeSort(arr,0,arr.length - 1,temp);
Date date1 = new Date();
String format1 = simpleDateFormat.format(date1);
System.out.println("排序后的时间是=" + format1);
}
//分 合
public static void mergeSort(int[] arr,int left,int right,int[] temp){
if (left < right){
int mid = (left + right) / 2; //中间索引
//向左递归进行分解
mergeSort(arr,left,mid,temp);
//向右递归分解
mergeSort(arr,mid + 1,right,temp);
//合并
merge(arr,left,mid,right,temp);
}
}
//合并的方法
/***
* @param arr 排序的原始数组
* @param left 左边有序序列的初始索引
* @param mid 中间索引
* @param right 右边索引
* @param temp 做中转的数组
*/
public static void merge(int[] arr,int mid,int left,int right,int[] temp){
int i = left; //初始化 i左边有序序列的初始索引
int j = mid+1; //初始化 j 右边有序序列的初始索引
int t =0; //指向temp 数组的当前索引
/*
* 先把左右两边的数据按照规则填充temp数组
* 直到左右两边的有序序列 有一边处理完毕为止
* */
while (i <=mid && j<= right){
//如果左边的有序序列的当前元素 小于等于右边有序
//即将左边的当前元素 填充到temp数组
if (arr[i]<= arr[j]){
temp[t] = arr[i];
t +=1;
i +=1;
}else {
//反之将右边有序序列填充temp
temp[t] = arr[j];
t +=1;
j +=1;
}
}
/*
* 二
* 把所有剩余数据的一边数据一次填充到temp
* */
while (i <=mid){ //左边的有序序列还有剩余的元素 全部填充temp
temp[t] = arr[i];
t +=1;
i +=1;
}
while (j <= right){
temp[t] = arr[j];
t +=1;
j +=1;
}
/*三
* 将temp 数组元素拷贝arr
* 注意 并不是每次拷贝
* */
t =0;
int tempLeft = left;
while (tempLeft <= left){
arr[tempLeft] = temp[t];
t +=1;
tempLeft +=1;
}
}
}
希尔排序
基本思想:将数列的下标安一定增量分组,对每组进行插入排序,随着增量减少,每组关键词增多;当增量减至1时,算法终止
public class ShellSort {
public static void main(String[] args) {
//创建要给80000个的随机数组
int[] arr = new int[80000];
for (int i = 0; i < 80000; i++) {
arr[i] = (int) (Math.random() * 8000000);//生成一个【0,8000000】
}
System.out.println("排序前");
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String format = simpleDateFormat.format(date);
System.out.println("排序前的时间是=" + format);
shellSort(arr);
Date date1 = new Date();
String format1 = simpleDateFormat.format(date1);
System.out.println("排序后的时间是=" + format1);
}
public static void shellSort(int[] arr) {
int temp = 0;
int count = 0;
//根据前面的逐步分析 循环处理
for (int gap = arr.length / 2; gap > 0; gap /= 2) {
for (int i = gap; i < arr.length; i++) {
//遍历各组中的所有元素
for (int j = i - gap; j >= 0; j -= gap) {
//如果当前元素大于加上 不长后的那个元素 说明交换
if (arr[j] > arr[j + gap]) {
temp = arr[j];
arr[j] = arr[j + gap];
arr[j + gap] = temp;
}
}
}
}
}
//对交换式的希尔排序进行进行优化->移位法
public static void shellSort2(int[] arr) {
//根据前面的逐步分析 循环处理
for (int gap = arr.length / 2; gap > 0; gap /= 2) {
//从第gap个元素 逐个对其所在的组进行直接插入排序
for (int i = gap; i < arr.length; i++) {
int j = i;
int temp = arr[i];
if (arr[j] < arr[j - gap]) {
while (j - gap >= 0 && temp < arr[j - gap]) {
//移动
arr[j] = arr[j - gap];
j -= gap;
}
//当退出while后 就给temp找到插入的位置
arr[j] = temp;
}
}
}
}
}