排序算法
1.直接插入排序
每次從無序區間的第一和元素開始,依次與有序區間内的元素從後往前比較 。如果目前有序區間内的元素大于無序區間,則将有序區間該下标元素後移 插入
public static void insertSort(int[] array) {
//有序區間:[0,i)
//無序區間:[i,array.length)
for (int i = 1; i < array.length; i++) {//外層循環找的是無序區間
int k = array[i];//k為無序區間第一個數
int j;//有序區間最後一個數
for (j = i - 1; j >= 0 && array[j] > k; j--) {//周遊的是有序區間
array[j + 1] = array[j];
}//從有序區間的最後一個元素開始比較
// 如果大于無序區間元素 則将有序區間的元素後移 最後插入元素
array[j + 1] = k;//因為最後循環退出的時候j--了 而真正要将無序區間插入的下标在後一個
}
}//直接插入排序
2.希爾排序
希爾排序時直接插入排序的更新版,将數組元素分成(size/2)/((size/3)+1)各組 進行直接插入排序 然後重複上述分組過程 分組 插排
public static void shellSort(int[] array) {
int gap = array.length;
while (true) {
gap = (gap / 3) + 1;//希爾排序的分組數 也可以為gap/2
insertSortWithGapa(array, gap);
if (gap == 1) {
break;
}
}
}
private static void insertSortWithGapa(int[] array, int gap) {
for (int i = gap; i < array.length; i++) {//從第二組請開始依次周遊整個數組
int k = array[i];
int j;
for (j = i - gap; j >= 0 && array[j] > k; j -= gap) {//将每一組的元素都與前面幾組相對應組的元素比較
array[j + gap] = array[j];
}
array[j+gap] = k;//當循環退出的時候 j的下标減了依次gap
}
}//希爾排序
3.直接選擇排序
整個數組看成一個無序區間 每次從無序區間中選擇最小(最大) 放入無序區間最前(最後)位置 ,一直到所有元素都排完
- 放在無序區間前面時 無序區間下标為[i,array,length)
- 放在無序區間後面時 無序區間下标為[0,array.length-i)
public static void selectSortSmall(int[] array) {
//無序下标:[i,array.length)
for (int i = 0; i < array.length - 1; i++) {//外層循環 需要循環array.length-1次才可以有序
int j;
int minIndex = i;//設定每次的起始位置為無序序列的第一個位置
for (j = minIndex; j < array.length; j++) { //在無序區間查找最小元素
if (array[j] < array[minIndex])
minIndex = j;
}
swap(array, minIndex, i);
}
}//直接選擇排序
//選擇無序區間最小的元素放到無序區間第一個位置
public static void selectSortBig(int[] array) {
for (int i = 0; i < array.length - 1; i++) {
// 無序區間: [0, array.length - i]
int max = 0;
for (int j = 1; j < array.length - i; j++) { //無序區間
if (array[j] > array[max]) {
max = j;
}
}
int t = array[max];
array[max] = array[array.length - i - 1];
array[array.length - i - 1] = t;
}
}//直接選擇排序
// 選擇無序區間最大的元素放到無序區間最後一個位置
private static void swap(int[] array, int i, int j) {
int t = array[i];
array[i] = array[j];
array[j] = t;
}
4.雙向選擇排序
直接從無序區間每次選出最大和最小元素 分别放在 無序區間最後和最前位置
特殊情況:當數組中最大元素在第一個位置時 經過與min 交換 目前最大元素下标發生變更 需特殊處理
public static void selectSortOP(int[] array) {
int begin = 0;
int end = array.length - 1;
// [begin,end] 表示整個無序區間
// 當無序區間内隻有一個數時停止排序
while (begin <= end) {
int minIndex = begin;
int maxIndex = end;//無序區間的最大值和最小值 均設定為第一個元素
for (int i = begin + 1; i <= maxIndex; i++) {
if (array[i] < array[minIndex])
minIndex = i;
if (array[i] > array[maxIndex])
maxIndex = i;
}
swap(array, minIndex, begin);
if (maxIndex == begin) {
maxIndex = minIndex;
}
swap(array, maxIndex, end);
begin++;
end--;
}
}//雙排
5.堆排序
-
首先對數組進行建堆 建大堆 排升序 建小堆 排降序(我是用大堆 排升序)
-
每次讓目前樹頂元素與最後一個元素進行交換(每交換一次 目前樹内元素減1)
-
對新的樹頂進行向下調整
public static void heapSort(int [] array){
createHeap(array);//建大堆
for(int i=0;i<array.length;i++) {
swap(array, 0, array.length-1-i);
//每次讓最大的元素與目前樹的最後一個節點交換
//在對新的樹頂做向下調整 找大的結點
shiftDownBig(array, array.length-i-1, 0);//目前無序期間的結點個數
}
}//堆排序
private static void shiftDownBig(int[] array, int size, int index) {
int left = 2 * index + 1;
while (left < size)
{
int max = left;
int right = left+1;
if (right < size)
{
if (array[right] > array[left])
{
max = right;
}
}
if (array[index] < array[max])
{
swap(array,index,max);
index = max;
left = 2 * index + 1;
}
else
break;
}
}//對指定下标元素做向下調整
private static void createHeap(int[] array) {
for(int j=(array.length-2)/2;j>=0;j--){
shiftDownBig(array,array.length,j);
}
}//建大堆 從最後一個葉子結點的雙親結點開始 依次對其做向下調整
6.冒泡排序
在無序區間,通過相鄰數的比較,将最大的數冒泡到無序區間的最後,持續這個過程,直到數組整體有序
public static void bubbleSort(int []array){
for(int i=0;i<array.length;i++){
for(int j=0;j<array.length-1-i;j++){
if(array[j]>array[j+1])
swap(array,j,j+1);//交換
}
}
}//冒泡排序
7.完整代碼
import java.sql.SQLOutput;
import java.util.Arrays;
import java.util.Random;
public class Sort {
public static void insertSort(int[] array) {
//有序區間:[0,i)
//無序區間:[i,array.length)
for (int i = 1; i < array.length; i++) {//外層循環找的是無序區間
int k = array[i];//k為無序區間第一個數
int j;//有序區間最後一個數
for (j = i - 1; j >= 0 && array[j] > k; j--) {//周遊的是有序區間
array[j + 1] = array[j];
}//從有序區間的最後一個元素開始比較
// 如果大于無序區間元素 則将有序區間的元素後移 最後插入元素
array[j + 1] = k;
}
}//直接插入排序
public static void shellSort(int[] array) {
int gap = array.length;
while (true) {
gap = (gap / 3) + 1;//希爾排序的分組數 也可以為gap/2
insertSortWithGapa(array, gap);
if (gap == 1) {
break;
}
}
}
private static void insertSortWithGapa(int[] array, int gap) {
for (int i = gap; i < array.length; i++) {//從第二組請開始依次周遊整個數組
int k = array[i];
int j;
for (j = i - gap; j >= 0 && array[j] > k; j -= gap) {//将每一組的元素都與前面幾組相對應組的元素比較
array[j + gap] = array[j];
}
array[j+gap] = k;//當循環退出的時候 j的下标減了依次gap
}
}//希爾排序
private static void swap(int[] array, int i, int j) {
int t = array[i];
array[i] = array[j];
array[j] = t;
}
public static void selectSortSmall(int[] array) {
//無序下标:[i,array.length)
for (int i = 0; i < array.length - 1; i++) {//外層循環 需要循環array.length-1次才可以有序
int j;
int minIndex = i;//設定每次的起始位置為無序序列的第一個位置
for (j = minIndex; j < array.length; j++) { //在無序區間查找最小元素
if (array[j] < array[minIndex])
minIndex = j;
}
swap(array, minIndex, i);
}
}//直接選擇排序
//選擇無序區間最小的元素放到無序區間第一個位置
public static void selectSortBig(int[] array) {
for (int i = 0; i < array.length - 1; i++) {
// 無序區間: [0, array.length - i]
int max = 0;
for (int j = 1; j < array.length - i; j++) { //無序區間
if (array[j] > array[max]) {
max = j;
}
}
int t = array[max];
array[max] = array[array.length - i - 1];
array[array.length - i - 1] = t;
}
}//直接選擇排序
// 選擇無序區間最大的元素放到無序區間最後一個位置
public static void selectSortOP(int[] array) {
int begin = 0;
int end = array.length - 1;
// [begin,end] 表示整個無序區間
// 當無序區間内隻有一個數時停止排序
while (begin <= end) {
int minIndex = begin;
int maxIndex = end;//無序區間的最大值和最小值 均設定為第一個元素
for (int i = begin + 1; i <= maxIndex; i++) {
if (array[i] < array[minIndex])
minIndex = i;
if (array[i] > array[maxIndex])
maxIndex = i;
}
swap(array, minIndex, begin);
if (maxIndex == begin) {
maxIndex = minIndex;
}
swap(array, maxIndex, end);
begin++;
end--;
}
}//雙排
public static void heapSort(int [] array){
createHeap(array);//建大堆
for(int i=0;i<array.length;i++) {
swap(array, 0, array.length-1-i);
//每次讓最大的元素與目前樹的最後一個節點交換
//在對新的樹頂做向下調整 找大的結點
shiftDownBig(array, array.length-i-1, 0);//目前無序期間的結點個數
}
}//堆排序
private static void shiftDownBig(int[] array, int size, int index) {
int left = 2 * index + 1;
while (left < size)
{
int max = left;
int right = left+1;
if (right < size)
{
if (array[right] > array[left])
{
max = right;
}
}
if (array[index] < array[max])
{
swap(array,index,max);
index = max;
left = 2 * index + 1;
}
else
break;
}
}//對指定下标元素做向下調整
private static void createHeap(int[] array) {
for(int j=(array.length-2)/2;j>=0;j--){
shiftDownBig(array,array.length,j);
}
}//建大堆 從最後一個葉子結點的雙親結點開始 依次對其做向下調整
public static void bubbleSort(int []array){
for(int i=0;i<array.length;i++){
for(int j=0;j<array.length-1-i;j++){
if(array[j]>array[j+1])
swap(array,j,j+1);
}
}
}//冒泡排序
public static void testSpeed() {
Random random = new Random(20190924);
int[] a = new int[10 * 10000];
for (int i = 0; i < 10 * 10000; i++) {
a[i] = random.nextInt(10 * 10000);
}
long begin = System.nanoTime();
heapSort(a);
long end = System.nanoTime();
double ms =(end - begin) * 1.0 / 1000 / 1000;
System.out.printf("一共耗時:%5f毫秒%n", ms);
}
public static void main(String[] args) {
int []a={9,5,2,7,3,6,4,8,4,3,9};
insertSort(a);
System.out.println(Arrays.toString(a));
System.out.println("b*========================");
int []b=a.clone();
bubbleSort(b);
System.out.println(Arrays.toString(b));
System.out.println("c*========================");
int []c=a.clone();
shellSort(c);
System.out.println(Arrays.toString(c));
System.out.println("d*========================");
int []d=a.clone();
heapSort(d);
System.out.println(Arrays.toString(d));
System.out.println("e*========================");
int []e=a.clone();
selectSortBig(e);
System.out.println(Arrays.toString(e));
System.out.println("f*========================");
int []f=a.clone();
selectSortSmall(f);
System.out.println(Arrays.toString(f));
System.out.println("g*========================");
int []g=a.clone();
selectSortOP(g);
System.out.println(Arrays.toString(g));
}
}