20200104:重温十大排序

温故而知新,可以为师矣

重新过一下已经掌握的排序方法,最基础的东西往往最关键!

写在最前面

新年伊始就得了场感冒,咳嗽从19年咳到了20年,考完研也休息的差不多了,大家一起共勉!

文章框架

在这里插入图片描述

快速排序

package com.immunize.December.sort;
 
/**
 * 快速排序1.2
 * 
 * @author Mr IMMUNIZE
 *
 */
public class Quick3 {
 
 public static void main(String[] args) {
   // 生成一个随机的数组
   int[] a = Generate(100, 10);
   // 对这个数组进行打印
   System.out.println("原始数组:");
   Print(a);
   // Print(Arrays.copyOfRange(a, 0, a.length));
   System.out.println("排序后的数组");
   quickSort(a, 0, a.length - 1);
   // SimpleSelectSort2(a);
   Print(a);
 }
 
 
 public static void quickSort(int[] a, int left, int right) {
   int q;
   if (left < right) {
    q = Partition(a, left, right);
    quickSort(a, left, q - 1);
    quickSort(a, q + 1, right);
   }
 
 }
 
 private static int Partition(int[] a, int left, int right) {
   int i, j, s;
   s = a[right];
   i = left - 1;
   for (j = left; j < right; j++) {
    if (a[j] <= a[right]) {
      i++;
      Swap(a, i, j);
    }
   }
   Swap(a, i + 1, right);
   return i + 1;
 }
 
 // Print函数
 public static void Print(int[] arr) {
   System.out.print("[");
   for (int i = 0; i < arr.length; i++) {
    if (i == arr.length - 1) {
      System.out.print(arr[i]);
      break;
    }
    System.out.print(arr[i] + ",");
   }
   System.out.print("]");
   System.out.println();
 }
 
 // 随机生成n个数字,组成随机数组函数Generate函数
 public static int[] Generate(int max, int length) {
   int[] arr = new int[length];
   for (int i = 0; i < length; i++) {
    arr[i] = (int) (Math.random() * max);
   }
   return arr;
 }
 
 // Swap函数
 public static void Swap(int[] arr, int i, int j) {
   int tmp = 0;
   tmp = arr[i];
   arr[i] = arr[j];
   arr[j] = tmp;
 }
}
 

上面这个版本是最优的改进版本,因为快速排序的精髓在与找到最优的标准,以下附上以数组中间值作为标准来进行比较的快排代码:

package com.immunize.December.sort;

/**
 * 快速排序1.1
 * 
 * @author Mr IMMUNIZE
 *
 */
public class Quick2 {

	public static void main(String[] args) {
		// 生成一个随机的数组
		int[] a = Generate(100, 10);
		// 对这个数组进行打印
		System.out.println("原始数组:");
		Print(a);
		// Print(Arrays.copyOfRange(a, 0, a.length));
		System.out.println("排序后的数组");
		QuickSort(a, 0, a.length - 1);
		// SimpleSelectSort2(a);
		Print(a);
	}

	/*
	 * 6 2 5 4 8 9 4 2 5 6 8 9 2 4 5 6 8 9
	 * 
	 */
	public static void QuickSort(int[] a, int left, int right) {
		int i, j, crit;
		if (left > right)
			return;
		i = left - 1;
		j = right + 1;
		// crit = a[0];
		crit = a[(left + right) / 2];
		while (true) {
			while (a[++i] < crit)
				;
			while (a[--j] > crit)
				;
			if (i >= j)
				break;
			Swap(a, i, j);
		}
		QuickSort(a, left, i - 1);
		QuickSort(a, j + 1, right);
	}

	// Print函数
	public static void Print(int[] arr) {
		System.out.print("[");
		for (int i = 0; i < arr.length; i++) {
			if (i == arr.length - 1) {
				System.out.print(arr[i]);
				break;
			}
			System.out.print(arr[i] + ",");
		}
		System.out.print("]");
		System.out.println();
	}

	// 随机生成n个数字,组成随机数组函数Generate函数
	public static int[] Generate(int max, int length) {
		int[] arr = new int[length];
		for (int i = 0; i < length; i++) {
			arr[i] = (int) (Math.random() * max);
		}
		return arr;
	}

	// Swap函数
	public static void Swap(int[] arr, int i, int j) {
		int tmp = 0;
		tmp = arr[i];
		arr[i] = arr[j];
		arr[j] = tmp;
	}
}

快速排序的最差时间复杂度为O(n²),但在大多数时候的效率是很好的,必须掌握。以下排序仅附上代码重写,不再赘述原理

堆排序

package com.immunize.December.sort;
 
/**
 * Heap排序:基于选择排序的改进
 * 
 * @author Mr IMMUNIZE
 *
 */
public class Heap {
 
 public static void main(String[] args) {
   // 生成一个随机的数组
   int[] a = Generate(100, 10);
   // 对这个数组进行打印
   System.out.println("原始数组:");
   Print(a);
   // Print(Arrays.copyOfRange(a, 0, a.length));
   System.out.println("排序后的数组");
   HeapSort(a);
   // SimpleSelectSort2(a);
   Print(a);
 }
 
 // 堆排序
 public static void HeapSort(int[] arr) {
   // 构造大根堆
   HeapInsert(arr);
   int size = arr.length;
   while (size > 1) {
    // 交换大根和最后一个值,即固定最大值
    Swap(arr, 0, size - 1);
    // size递减
    size--;
 
    Heapify(arr, 0, size);
   }
 
 }
 
 // 构造大根堆(通过新插入的数上升)
 public static void HeapInsert(int[] arr) {
   // 定义所使用的变量
   int i, curIndex, faIndex;
   for (i = 0; i < arr.length; i++) {
    // 确定当前索引值
    curIndex = i;
    // 计算父节点索引值
    faIndex = (curIndex - 1) / 2;
    // 遍历,构造大根堆
    while (arr[curIndex] > arr[faIndex]) {
      Swap(arr, curIndex, faIndex);
      // 将当前索引和父节点索引归位
      curIndex = faIndex;
      faIndex = (curIndex - 1) / 2;
    }
   }
 }
 
 // 将剩余的数构造成大根堆(通过顶端的数下降)
 public static void Heapify(int[] arr, int index, int size) {
   // 定义使用的变量
   int left, right, largerIndex;
   // 计算当前节点的左右节点索引
   left = 2 * index + 1;
   right = 2 * index + 2;
   // 确保较小的子节点:左节点小于待排序节点个数
   while (left < size) {
    // 找到左右节点中较大的节点索引
    if (arr[left] < arr[right] && right < size)
      largerIndex = right;
    else
      largerIndex = left;
 
    // 比较当前索引和左右节点中较大的索引处的值,若当前索引较大,则已经是大根堆,跳出循环即可。
    if (arr[index] > arr[largerIndex]) {
      largerIndex = index;
      break;
    }
    Swap(arr, index, largerIndex);
    // 重新指向当前索引和当前索引的左右子节点
    index = largerIndex;
    left = 2 * index + 1;
    right = 2 * index + 2;
 
   }
 }
 
 // 交换数组中两个元素的值
 public static void Swap(int[] arr, int i, int j) {
   int temp = arr[i];
   arr[i] = arr[j];
   arr[j] = temp;
 }
 
 // Print函数
 public static void Print(int[] arr) {
   System.out.print("[");
   for (int i = 0; i < arr.length; i++) {
    if (i == arr.length - 1) {
      System.out.print(arr[i]);
      break;
    }
    System.out.print(arr[i] + ",");
   }
   System.out.print("]");
   System.out.println();
 }
 
 // 随机生成n个数字,组成随机数组函数Generate函数
 public static int[] Generate(int max, int length) {
   int[] arr = new int[length];
   for (int i = 0; i < length; i++) {
    arr[i] = (int) (Math.random() * max);
   }
   return arr;
 }
}
 

希尔排序

package com.immunize.December.sort;
 
public class Shell {
 public static void main(String[] args) {
 
   // 生成原始数组
   int[] a = Generate(100, 10);
   // 原始数组打印
   System.out.println("原始数组:");
   Print(a);
   // 希尔排序后的数组打印
   System.out.println("排序后的数组");
   // shellSort1(a);
   shellSort2(a);
   Print(a);
 }
 
 public static void shellSort2(int[] a) {
   int gap = a.length / 2;
   int i, j;
   for (; gap > 0; gap /= 2) {
    for (i = gap; i < a.length; i++) {
      j = i;
      while (j - gap >= 0 && a[j] < a[j - gap]) {
       Swap(a, j, j - gap);
       j -= gap;
      }
    }
   }
 }
 
 // 希尔排序
 public static void shellSort1(int[] arr) {
   int i, j, k, tmp;
   int gap = arr.length / 2;
   while (gap > 0) {
    for (k = 0; k < gap; k++) {
      for (i = k + gap; i < arr.length; i += gap) {
       for (j = i - gap; j >= k; j -= gap) {
         if (arr[j] > arr[j + gap]) {
          Swap(arr, j, j + gap);
         } else {
          break;
         }
       }
      }
    }
    gap /= 2;
   }
 
 }
 
 // Print函数
 public static void Print(int[] arr) {
   System.out.print("[");
   for (int i = 0; i < arr.length; i++) {
    if (i == arr.length - 1) {
      System.out.print(arr[i]);
      break;
    }
    System.out.print(arr[i] + ",");
   }
   System.out.print("]");
   System.out.println();
 }
 
 // 随机生成n个数字,组成随机数组函数Generate函数
 public static int[] Generate(int max, int length) {
   int[] arr = new int[length];
   for (int i = 0; i < length; i++) {
    arr[i] = (int) (Math.random() * max);
   }
   return arr;
 }
 
 // Swap函数
 public static void Swap(int[] arr, int i, int j) {
   int tmp = 0;
   tmp = arr[i];
   arr[i] = arr[j];
   arr[j] = tmp;
 }
}
 

计数排序

 
package com.immunize.December.sort;
 
public class Count {
 
 public static void main(String[] args) {
   // 生成一个随机的数组
   int[] a = Generate(100, 10);
   // 对这个数组进行打印
   System.out.println("原始数组:");
   Print(a);
   // Print(Arrays.copyOfRange(a, 0, a.length));
   System.out.println("排序后的数组");
   Print(countSort(a));
 
 }
 
 public static int[] countSort(int[] a) {
   // 找出数组中的最大值
   int max = Integer.MIN_VALUE;
   for (int num : a) {
    max = Math.max(max, num);
   }
 
   // 初始化计数数组
   int[] count = new int[max + 1];
   // 对数组计数
   for (int num : a) {
    count[num]++;
   }
 
   // 创建结果数组
   int[] result = new int[a.length];
   int index = 0;
   for (int i = 0; i < count.length; i++) {
    while (count[i] > 0) {
      result[index++] = i;
      count[i]--;
    }
   }
   return result;
 
 }
 
 // Print函数
 public static void Print(int[] arr) {
   System.out.print("[");
   for (int i = 0; i < arr.length; i++) {
    if (i == arr.length - 1) {
      System.out.print(arr[i]);
      break;
    }
    System.out.print(arr[i] + ",");
   }
   System.out.print("]");
   System.out.println();
 }
 
 // 随机生成n个数字,组成随机数组函数Generate函数
 public static int[] Generate(int max, int length) {
   int[] arr = new int[length];
   for (int i = 0; i < length; i++) {
    arr[i] = (int) (Math.random() * max);
   }
   return arr;
 }
 
 // Swap函数
 public static void Swap(int[] arr, int i, int j) {
   int tmp = 0;
   tmp = arr[i];
   arr[i] = arr[j];
   arr[j] = tmp;
 }
}
 

桶排序

package com.immunize.December.sort;
 
public class Radix {
 
 public static void main(String[] args) {
   // 生成一个随机的数组
   int[] a = Generate(100, 10);
   // 对这个数组进行打印
   System.out.println("原始数组:");
   Print(a);
   System.out.println("排序后的数组");
   RadixSort(a, 3);
   Print(a);
 }
 
 public static void RadixSort(int[] arr, int max) {
 
   // count数组用来计数
   int[] count = new int[arr.length];
   // bucket用来当桶(在下面你就理解了什么是桶了),放数据,取数据
   int[] bucket = new int[arr.length];
 
   // k表示第几位,1代表个位,2代表十位,3代表百位
   for (int k = 1; k <= max; k++) {
    // 把count置空,防止上次循环的数据影响
    for (int i = 0; i < arr.length; i++) {
      count[i] = 0;
    }
 
    // 分别统计第k位是0,1,2,3,4,5,6,7,8,9的数量
    // 以下便称为桶
    // 即此循环用来统计每个桶中的数据的数量
    for (int i = 0; i < arr.length; i++) {
      count[getFigure(arr[i], k)]++;
    }
 
    // 利用count[i]来确定放置数据的位置
    for (int i = 1; i < arr.length; i++) {
      count[i] = count[i] + count[i - 1];
    }
    // 执行完此循环之后的count[i]就是第i个桶右边界的位置
 
    // 利用循环把数据装入各个桶中,注意是从后往前装
    // 这里是重点,一定要仔细理解
    for (int i = arr.length - 1; i >= 0; i--) {
      int j = getFigure(arr[i], k);
      bucket[count[j] - 1] = arr[i];
      count[j]--;
    }
 
    // 将桶中的数据取出来,赋值给arr
    for (int i = 0, j = 0; i < arr.length; i++, j++) {
      arr[i] = bucket[j];
    }
 
   }
 }
 
 // 此函数返回整型数i的第k位是什么
 public static int getFigure(int i, int k) {
   int[] a = { 1, 10, 100 };
   return (i / a[k - 1]) % 10;
 }
 
 // Print函数
 public static void Print(int[] arr) {
   System.out.print("[");
   for (int i = 0; i < arr.length; i++) {
    if (i == arr.length - 1) {
      System.out.print(arr[i]);
      break;
    }
    System.out.print(arr[i] + ",");
   }
   System.out.print("]");
   System.out.println();
 }
 
 // 随机生成n个数字,组成随机数组函数Generate函数
 public static int[] Generate(int max, int length) {
   int[] arr = new int[length];
   for (int i = 0; i < length; i++) {
    arr[i] = (int) (Math.random() * max);
   }
   return arr;
 }
 
 // Swap函数
 public static void Swap(int[] arr, int i, int j) {
   int tmp = 0;
   tmp = arr[i];
   arr[i] = arr[j];
   arr[j] = tmp;
 }
}
 

冒泡排序

package com.immunize.December.sort;
 
public class Bubble {
 
 public static void main(String[] args) {
   // 生成一个随机的数组
   int[] a = Generate(100, 10);
   // 对这个数组进行打印
   System.out.println("原始数组:");
   Print(a);
   // Print(Arrays.copyOfRange(a, 0, a.length));
   System.out.println("排序后的数组");
   bubbleSort(a);
   // SimpleSelectSort2(a);
   Print(a);
 
 }
 
 public static void bubbleSort(int[] a) {
   // 两两对比,每次将最大的放到最后面
   int i, j;
   // i为遍历指针,从0-a.length-2
   for (i = 0; i < a.length - 1; i++) {
    // j为比较指针,从1-(a.length-i)
    for (j = 1; j < a.length - i; j++) {
      if (a[j] < a[j - 1])
       Swap(a, j, j - 1);
    }
   }
 }
 
 // Print函数
 public static void Print(int[] arr) {
   System.out.print("[");
   for (int i = 0; i < arr.length; i++) {
    if (i == arr.length - 1) {
      System.out.print(arr[i]);
      break;
    }
    System.out.print(arr[i] + ",");
   }
   System.out.print("]");
   System.out.println();
 }
 
 // 随机生成n个数字,组成随机数组函数Generate函数
 public static int[] Generate(int max, int length) {
   int[] arr = new int[length];
   for (int i = 0; i < length; i++) {
    arr[i] = (int) (Math.random() * max);
   }
   return arr;
 }
 
 // Swap函数
 public static void Swap(int[] arr, int i, int j) {
   int tmp = 0;
   tmp = arr[i];
   arr[i] = arr[j];
   arr[j] = tmp;
 }
}
 

鸡尾酒排序

package com.immunize.December.sort;
 
import java.util.Arrays;
 
public class Shaker {
 
 public static void main(String[] args) {
   // 生成一个随机的数组
   int[] a = Generate(100, 10);
   // 对这个数组进行打印
   System.out.println("原始数组:");
   Print(a);
   // Print(Arrays.copyOfRange(a, 0, a.length));
   System.out.println("排序后的数组");
   ShakerSort(a);
   // SimpleSelectSort2(a);
   Print(a);
   // Print(cocktailSort(a));
 }
 
 public static void ShakerSort(int[] a) {
   int i, j, left, right, shift;
   left = 0;
   right = a.length - 1;
   shift = 0;
   while (left < right) {
 
    for (i = left; i < right; i++) {
      if (a[i] > a[i + 1]) {
       Swap(a, i, i + 1);
       shift = i;
      }
    }
    right = shift;
    for (j = right; j > left; j--) {
      if (a[j - 1] > a[j]) {
       Swap(a, j, j - 1);
       shift = j;
      }
    }
    left = shift;
   }
 }
 
 public static int[] cocktailSort(int[] src) {
   int len = src.length;
   // 将最小值排到队尾
   for (int i = 0; i < len / 2; i++) {
    for (int j = i; j < len - i - 1; j++) {
      if (src[j] < src[j + 1]) {
       int temp = src[j];
       src[j] = src[j + 1];
       src[j + 1] = temp;
      }
      System.out.println("交换小" + Arrays.toString(src));
    }
    // 将最大值排到队头
    for (int j = len - 1 - (i + 1); j > i; j--) {
      if (src[j] > src[j - 1]) {
       int temp = src[j];
       src[j] = src[j - 1];
       src[j - 1] = temp;
      }
      System.out.println("交换大" + Arrays.toString(src));
    }
    System.out.println("第" + i + "次排序结果:" + Arrays.toString(src));
   }
   return src;
 }
 
 // Print函数
 public static void Print(int[] arr) {
   System.out.print("[");
   for (int i = 0; i < arr.length; i++) {
    if (i == arr.length - 1) {
      System.out.print(arr[i]);
      break;
    }
    System.out.print(arr[i] + ",");
   }
   System.out.print("]");
   System.out.println();
 }
 
 // 随机生成n个数字,组成随机数组函数Generate函数
 public static int[] Generate(int max, int length) {
   int[] arr = new int[length];
   for (int i = 0; i < length; i++) {
    arr[i] = (int) (Math.random() * max);
   }
   return arr;
 }
 
 // Swap函数
 public static void Swap(int[] arr, int i, int j) {
   int tmp = 0;
   tmp = arr[i];
   arr[i] = arr[j];
   arr[j] = tmp;
 }
}
 

鸡尾酒排序这里多说一点,两种写法都在代码中呈现出来,ShakerSort/cocktailSort都称为鸡尾酒排序

选择排序

package com.immunize.December.sort;
 
import java.util.Arrays;
 
public class Select {
 
 public static void main(String[] args) {
   // 生成一个随机的数组
   int[] a = Generate(100, 10);
   // 对这个数组进行打印
   System.out.println("原始数组:");
   Print(a);
   // Print(Arrays.copyOfRange(a, 0, a.length));
   System.out.println("排序后的数组");
   // selectSort1(a);
   selectSort2(a);
 
   // SimpleSelectSort2(a);
   Print(a);
 }
 
 public static void selectSort1(int[] a) {
   int i, j, tmp;
   for (i = 0; i < a.length - 1; i++) {
    // 获取当前索引
    tmp = i;
    for (j = i + 1; j < a.length; j++) {
      if (a[tmp] > a[j]) {
       Swap(a, j, tmp);
      }
    }
   }
 }
 
 public static void selectSort2(int[] a) {
   int i, j, tmp;
   for (i = 0; i < a.length - 1; i++) {
    tmp = i;
    Swap(a, tmp, FindMinIndex(Arrays.copyOfRange(a, i, a.length)) + i);
   }
 }
 
 public static int FindMinIndex(int[] a) {
   int i, min, minIndex = 0;
   min = a[0];
   for (i = 1; i < a.length; i++) {
    if (a[i] < min) {
      min = a[i];
      minIndex = i;
    }
   }
   return minIndex;
 }
 
 // Print函数
 public static void Print(int[] arr) {
   System.out.print("[");
   for (int i = 0; i < arr.length; i++) {
    if (i == arr.length - 1) {
      System.out.print(arr[i]);
      break;
    }
    System.out.print(arr[i] + ",");
   }
   System.out.print("]");
   System.out.println();
 }
 
 // 随机生成n个数字,组成随机数组函数Generate函数
 public static int[] Generate(int max, int length) {
   int[] arr = new int[length];
   for (int i = 0; i < length; i++) {
    arr[i] = (int) (Math.random() * max);
   }
   return arr;
 }
 
 // Swap函数
 public static void Swap(int[] arr, int i, int j) {
   int tmp = 0;
   tmp = arr[i];
   arr[i] = arr[j];
   arr[j] = tmp;
 }
}
 

插入排序

package com.immunize.December.sort;
 
public class Insert {
 
 public static void main(String[] args) {
   // 生成一个随机的数组
   int[] a = Generate(100, 10);
   // 对这个数组进行打印
   System.out.println("原始数组:");
   Print(a);
   System.out.println("排序后的数组");
   insertSort(a);
   // SimpleSelectSort2(a);
   Print(a);
 
 }
 
 // 插入排序
 public static void insertSort(int[] a) {
   int i, j, tmp;
   // 遍历
   // i从1-末尾
   for (i = 1; i < a.length; i++) {
    // 当前值tmp
    tmp = a[i];
    // 前一个值的索引
    j = i - 1;
    // 当前值与每一个在其之前的数比较
    while (tmp < a[j]) {
      // 前值较大的话则需要往后移
      a[j + 1] = a[j];
      j--;
      // 移动的上限是第一个值
      if (j == -1) {
       break;
      }
    }
    // 跳出循环,当前值赋值到空出来的那个位置
    a[j + 1] = tmp;
   }
 }
 
 // Print函数
 public static void Print(int[] arr) {
   System.out.print("[");
   for (int i = 0; i < arr.length; i++) {
    if (i == arr.length - 1) {
      System.out.print(arr[i]);
      break;
    }
    System.out.print(arr[i] + ",");
   }
   System.out.print("]");
   System.out.println();
 }
 
 // 随机生成n个数字,组成随机数组函数Generate函数
 public static int[] Generate(int max, int length) {
   int[] arr = new int[length];
   for (int i = 0; i < length; i++) {
    arr[i] = (int) (Math.random() * max);
   }
   return arr;
 }
 
 // Swap函数
 public static void Swap(int[] arr, int i, int j) {
   int tmp = 0;
   tmp = arr[i];
   arr[i] = arr[j];
   arr[j] = tmp;
 }
}
 

基数排序

package com.immunize.Arithmetic;
 
/**
 * 基数排序法
 * 
 * @author Mr IMMUNIZE
 *
 */
public class RadixSort {
 
  public static void main(String[] args) {
     int[] data = { 73, 22, 93, 43, 55, 14, 28, 65, 39, 81 };
     int[][] temp = new int[10][10];
     int[] order = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
     int i, j, k, n, lsd;
     k = 0;
     n = 1;
     System.out.println("排序前:");
     Print(data);
     System.out.println();
     while (n <= 10) {
       for (i = 0; i < 10; i++) {
          // 拿到个位数数字
          lsd = ((data[i] / n) % 10);
          // 将该数据存放在对应的列上,21就放在第一列,89就放在第9列
          temp[lsd][order[lsd]] = data[i];
          // order[lsd]表示行数,行数递增
          order[lsd]++;
       }
 
       for (i = 0; i < 10; i++) {
          // 重新排列,先列后行
          if (order[i] != 0) {
            // 先列再行,每一行只有一个数据,每一列的数据按照行序排列
            for (j = 0; j < order[i]; j++) {
               data[k] = temp[i][j];
               k++;
            }
          }
          order[i] = 0;
       }
       n *= 10;
       k = 0;
     }
     System.out.println("排序后:");
     Print(data);
  }
 
  public static void Print(int[] number) {
 
     for (int i = 0; i < number.length; i++) {
       System.out.print(number[i] + " ");
     }
  }
}
 
 

基数排序代码未重写,是直接取自我之前20191015的博客。

结语

至此,十大排序除了归并排序其余的都已经附上重写代码,而归并排序实际上是Java中Arrays的sort方法的本质,我们明天给予说明。

发布了99 篇原创文章 · 获赞 11 · 访问量 4188
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章