1、冒泡排序
/**
* @Author zb
* @Date 2018/8/13
*/
public class BubbleSort {
/**
* 冒泡排序
* @param arr
*/
public static void bubbleSort(int[] arr){
if(arr == null || arr.length < 2){
return ;
}
for (int e = arr.length - 1; e > 0; e--){
for(int i = 0; i < e; i++){
if(arr[i] > arr[i+1]){
swap(arr, i, i+1);
}
}
}
}
public static void swap(int[] arr, int i, int j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
public static void main(String[] args) {
int arr[] = {5,4,9,8,7,6,0,1,3,2};
bubbleSort(arr);
for(int i = 0; i < arr.length; i++){
System.out.print(arr[i]+" ");
}
}
}
1.1第一种优化—外层循环优化
问题
有的冒泡经过第一轮的交换已经是有序的了,如:2 1 3 4。数据越多的时候越慢,非常不适合大数据的排序
解决办法
如果用一个flag来判断一下,当前数组是否已经有序,如果有序就退出循环,这样可以明显的提高冒泡排序的性能。
package bubbleSort;
import java.util.Arrays;
import org.junit.Test;
/**
* 冒泡排序的性能分析和算法优化(外层循环优化)
* @author dell
*
*/
public class BubbeSort02 {
@Test
public void test1(){
boolean flag = true;
int[] arr = {2,1,3,4,5};
int temp;
for (int i = 0; i < arr.length-1; i++) {
for (int j = 0; j < arr.length-1-i; j++) {
if(arr[j]>arr[j+1]){
temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
flag=false;
}
}
if(!flag){
//没有发生交换则退出循环;
break;
}
}
System.out.println(Arrays.toString(arr));
}
}
1.2第二种优化—内层循环优化
/**
* 冒泡排序的性能分析和算法优化(内层循环优化)
*/
@Test
public void test2(){
int[] arr = {22,1,10,5};
//标记最后一次交换的位置
for (int i = 0; i < arr.length-1; i++) {
int flag = 0;
int temp;
for (int j = 0; j < arr.length-i-1; j++) {
if(arr[j]>arr[j+1]){
temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
//当位置发生改变,flag的值就发生变化
flag=1;
}
}
//判断标志位flag有没有发生变化,没有就直接结束内层循环
if(flag==0){
return;
}
}
System.out.println(Arrays.toString(arr));
}
}
2、插入排序
/**
* @Author zb
* @Date 2018/8/13
*/
public class InsertionSort {
/**
* 插入排序
* @param arr
*/
public static void insertionSort(int[] arr){
if(arr == null || arr.length < 2){
return ;
}
for(int i = 1; i < arr.length; i++){
for(int j = i-1; j>= 0; j--){
if(arr[j] > arr[j+1]){
swap(arr,j,j+1);
}
}
}
}
public static void swap(int[] arr, int i, int j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
public static void main(String[] args) {
int arr[] = {5,4,9,8,7,6,0,1,3,2};
insertionSort(arr);
for(int i = 0; i < arr.length; i++){
System.out.print(arr[i]+" ");
}
}
}
3、选择排序
/**
* @Author zb
* @Date 2018/8/13
*/
public class SelectSort {
/**
* 选择排序
* @param arr
*/
public static void selectSort(int[] arr){
if(arr == null || arr.length < 2){
return ;
}
for(int i = 0; i < arr.length-1; i++){
int minIndex = i;
//找出每次遍历的最小值
for(int j = i + 1; j < arr.length; j++){
minIndex = arr[j] < arr[minIndex] ? j : minIndex;
}
swap(arr,i,minIndex);
}
}
public static void swap(int[] arr, int i, int j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
public static void main(String[] args) {
int arr[] = {5,4,9,8,7,6,0,1,3,2};
selectSort(arr);
for(int i = 0; i < arr.length; i++){
System.out.print(arr[i]+" ");
}
}
}
4、堆排序
/**
* @Author zb
* @Date 2018/8/13
*/
public class HeapSort {
/**
* 堆排序
* @param arr
*/
public static void heapSort(int[] arr){
if(arr == null || arr.length < 2){
return ;
}
//从0—i依次建立大根堆
for(int i = 0; i < arr.length; i++){
heapInsert(arr, i);
}
int heapSize = arr.length;
//最后一个位置的数跟0位置上的数交换(大根堆中0位置的数最大)
//--heapsize:下标从0开始,所以要减1
swap(arr, 0, --heapSize);
//排序
while (heapSize > 0){
//调整大根堆
heapify(arr, 0, heapSize);
//再和0位置上的数交换
swap(arr, 0, --heapSize);
}
}
/**
* 建立大根堆:已知结点为i,则它的父结点为(i-1)/2,它的左孩子结点为2*i+1,右孩子为:2*i+2
* @param arr
* @param index
*/
public static void heapInsert(int[] arr, int index){
//如果当前结点的值比父结点的值大,则交换
while(arr[index] > arr[(index-1)/2]){
swap(arr, index, (index - 1)/2);
//index被赋值为父节点的下标,继续和上面的父节点比较
index = (index - 1)/2;
}
}
/**
* 调整大根堆
* @param arr
* @param index
* @param heapSize 堆的大小,标记是否越界,其值小于等于数组的大小
*/
public static void heapify(int[] arr, int index, int heapSize){
//当前结点的左孩子的下标
int left = index * 2 +1;
while(left < heapSize){
//left+1:当前结点的右孩子的下标
//largest:表示左右孩子中较大者的下标
int largest = left + 1 < heapSize && arr[left + 1] > arr[left] ? left + 1 : left;
//和当前结点比较,哪个更大
largest = arr[largest] > arr[index] ? largest : index;
//当前结点比左右孩子的值都大,不用调整
if(largest == index){
break;
}
swap(arr, largest, index);
//继续调整,把较小值向下沉
index = largest;
left = index * 2 + 1;
}
}
public static void swap(int[] arr, int i, int j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
public static void main(String[] args) {
int arr[] = {5,4,9,8,7,6,0,1,3,2,};
heapSort(arr);
for(int i = 0; i < arr.length; i++){
System.out.print(arr[i]+" ");
}
}
}
5、并归排序
public static void mergeSort(int[] arr){
if(arr == null || arr.length < 2){
return;
}
mergeProcess(arr, 0, arr.length - 1);
}
//并归排序过程
public static void mergeProcess(int[] arr, int left, int right){
//只有一个数,已经排好了
if(left == right){
return ;
}
//left和right的中点位置。相当于mid = (left + right) / 2
int mid = left + ((right - left) >> 1);
//递归排好左边
mergeProcess(arr, left, mid);
//递归排好右边
mergeProcess(arr, mid + 1, right);
//整体排好
merge(arr, left, mid, right);
}
//把已经排好序的左右两边排好序
public static void merge(int[] arr, int left, int mid, int right){
//辅助数组,left到rihgt上有多少个数。
int[] help = new int[right - left + 1];
int i = 0;
int p1 = left;
int p2 = mid + 1;
//定义两个下标,分别指向左右两边的最左侧
//谁小,填谁
while(p1 <= mid && p2 <= right){
help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
}
//左右两部分中,必有且只有一个越界
while(p1 <= mid){
help[i++] = arr[p1++];
}
while (p2 <= right){
help[i++] = arr[p2++];
}
//把help中排好的序复制到arr中
for(i = 0; i < help.length; i++){
arr[left + i] = help[i];
}
}
public static void main(String[] args) {
int[] array = {3,4,6,1,2,3};
mergeSort(array);
for(int i = 0; i < array.length; i++){
System.out.print(array[i] + " ");
}
}