1.八大排序
2.冒泡排序
static void bubbling(int[] arr){
final int length = arr.length;
for (int i = 0;i < length - 1;i++){
for (int j = 0;j < length - i - 1;j++){
if (arr[j] > arr[j + 1]){
int t = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = t;
}
}
}
}
3.插入排序
static void insertion(int[] arr){
final int length = arr.length;
for (int i = 1;i < length;i++){
//&& arr[j] < arr[j - 1],排序过后前面的数已经有序
//arr[j] < arr[j - 1],前面已经有序,所以前面肯定没有比arr[j]大的数
//这样减少内层循环
for (int j = i;j > 0 && arr[j] < arr[j - 1];j--){
if (arr[j] < arr[j - 1]){
int t = arr[j];
arr[j] = arr[j -1];
arr[j - 1] = t;
}
}
}
}
4.选择排序
static void selection(int[] arr){
final int length = arr.length;
int maxIndex = 0;
for (int i = 0;i < length - 1;i++){
int j = 0;
for (;j < length - i;j++){
if (arr[maxIndex] < arr[j]){
maxIndex = j;
}
}
j--;
int t = arr[maxIndex];
arr[maxIndex] = arr[j];
arr[j] = t;
maxIndex = 0;
}
}
5.希尔排序
/**
* 希尔排序-三层循环
* date -> 0 1 2 3 4 5 6 7 8 9,gap=2
* 要对index=1之后的所有的数据进行插入排序,不需要必须对gap间隔的一组数进行排序
* 所以直接让i每次加1,直到小于length
* @param array
*/
static void shellToImprove(int[] array){
final int length = array.length;
int gap = length / 2;
while (gap > 0){
for (int i = gap;i < length;i++){
for (int j = i;j > gap - 1 && array[j] < array[j - gap];j -= gap){
if (array[j] < array[j - gap]){
int t = array[j];
array[j] = array[j - gap];
array[j - gap] = t;
}
}
}
gap /= 2;
}
}
/**
* 希尔排序-四层循环
* date -> 0 1 2 3 4 5 6 7 8 9,gap=2
* 四层循环的写法,会先对2 4 6 8,在对3 5 7 9进行插入排序
* @param arr
*/
static void shell(int[] arr){
final int length = arr.length;
//每次跳跃的间隔,最后一次为1
int gap = length / 2;
//0 1 2 3 4 5 6 7 8 9
//控制每次跳跃的间隔,10个数5 2 1
while (gap > 0){
//循环间隔之间的数,如gap=5,0->5,1->6,2->7,3->8,4->9共5次
for (int i = 0;i < gap;i++){
//执行插入排序的逻辑,不过每次跳跃的不是1,而是gap
for (int j = i + gap;j < length;j += gap){
//k > gap - 1,插入排序gap=1,k>1-1=0
for (int k = j;k > gap - 1 && arr[k] < arr[k - gap];k -= gap){
if (arr[k] < arr[k - gap]){
int t = arr[k];
arr[k] = arr[k - gap];
arr[k - gap] = t;
}
}
}
}
gap /= 2;
}
}
6.快速排序
static void quick(int[] arr){
final int length = arr.length;
//使用LinkedList作为栈,记录要比较数据的间隔的索引
LinkedList<Integer> stack = new LinkedList<>();
int left = 0;
int right = length - 1;
int start;
int end;
//push进行压栈
stack.push(left);
stack.push(right);
int key;
while (!stack.isEmpty()){
//pop出栈
right = end = stack.pop();
left = start = stack.pop();
//分割数组的元素
key = arr[left];
//和递归的操作一致,进行key的两边数据的分割
while (left < right){
while (key < arr[right] && left < right){
right--;
}
arr[left] = arr[right];
while (key > arr[left] && left < right){
left++;
}
arr[right] = arr[left];
}
arr[left] = key;
//如果左边元素大于1,进行压栈
if (start < left - 1){
stack.push(start);
stack.push(left - 1);
}
//如果右边元素大于1,进行压栈
if (end > left + 1){
stack.push(left + 1);
stack.push(end);
}
}
}
static void quick(int[] arr,int left,int right){
if (left < right){
//position索引就是等分左右的数,所以我们在对其左、有进行排序
int position = position(arr,left,right);
quick(arr,left,position - 1);
quick(arr,position + 1,right);
}
}
static int position(int[] arr,int left,int right){
//分割的数据,这个数据越是处于要排序的中间,排序的效率越高
//所以我们可以通过三数取中、或者多次探测的方式保证这个数据的准确
int key = arr[left];
while (left < right){
//从右边找小于等于key的数的索引
while (arr[right] > key && left < right){
right--;
}
//将小于等于key的数放在左边
arr[left] = arr[right];
//从左边找大于等于key的数,然后放在右边,arr[left] <= key
while (arr[left] < key && left < right){
left++;
}
arr[right] = arr[left];
}
//将key放在left索引的位置
arr[left] = key;
return left;
}
7.堆排序
static void heap(int[] arr){
final int length = arr.length;
for (int i = 0;i < length;i++){
//计算出最后一个非叶子节点,length - i表示排除已经通过交换有序的数据
int first = ((length - i) / 2) - 1;
//从最后一个非叶子节点开始调整堆,直到根节点
for (;first > -1;first--){
buildHeap(arr,first,length - i);
}
//现在arr[0]是未排序数据中最大的值,我们与最后一个元素进行交换
int t = arr[0];
arr[0] = arr[length - i - 1];
arr[length - i - 1] = t;
}
}
/**
* 创建堆
* @param arr 数组
* @param current 当前节点
* @param size 并非数组中所有的数都要经历重建堆的过程,已经从顶部交换的数据
* 不需要再经历创建堆的过程
*/
static void buildHeap(int[] arr,int current,int size){
//左子女
int left = current * 2 + 1;
//右子女
int right = current * 2 + 2;
//假定当前节点为最大
int max = current;
//如果当前节点的左右子女比他大,就改变最大的索引
//判断left < size,当前节点为叶子,使得数据越界
if (left < size){
if (arr[max] < arr[left]){
max = left;
}
}
if (right < size){
if (arr[max] < arr[right]){
max = right;
}
}
//最大值不是当前节点,进行交换
if (max != current){
int t = arr[current];
arr[current] = arr[max];
arr[max] = t;
//交换之后,其左右子女有可能和最大堆的性质不符合,我们进行递归调整
buildHeap(arr,max,size);
}
}
8.归并排序
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,right,mid,temp);
}
}
static void merge(int[] arr,int left,int right,int mid,int[] temp){
//n用来数据在temp中的索引
int n = left;
//第一组数据的开始索引
int leftStart = left;
//第二组数据的开始索引
int rightStart = mid + 1;
//temp要加入的数据
int total = right - left + 1;
for (int i = 0;i < total;i++){
if (leftStart > mid){
//说明第一组数据全部添加到temp中
temp[n] = arr[rightStart++];
}else if (rightStart > right){
//说明第二组数据全部添加到temp中
temp[n] = arr[leftStart++];
}else {
//没有哪一组数据全部添加到temp中,所以进行两组数据的比较
if (arr[leftStart] < arr[rightStart]){
temp[n] = arr[leftStart++];
}else {
temp[n] = arr[rightStart++];
}
}
n++;
}
//将temp中有序的数据拷贝到arr中
for (;left <= right;left++){
arr[left] = temp[left];
}
}
9.桶排序
/**
* 基数排序-先对数据的个位进行排序,得到一段相对于另一段有序的数据
* 然后逐个对更高位进行排序
* @param arr
*/
static void radixSort(int[] arr){
//记录每次数据要整除的数字,如1 10 100
int n = 1;
//通过一个二维数字保存每一个位置有序的数据
//相当于一个桶,一共有十个
int[][] arrs = new int[10][arr.length];
//记录arrs每一个桶中数据的个数
int[] count = new int[10];
int temp;
int num;
int c;
while (n < 20){
//将arr中的数据放入相应的桶中
//如在对个位进行操作的时候,21,放入3个桶中
for (int i = 0;i < arr.length;i++){
//得到数据相应的位置的数据
temp = (arr[i] / n) % 10;
//获取当前位置的桶已经保存的数据的个数
num = count[temp];
arrs[temp][num] = arr[i];
count[temp] = num + 1;
}
num = 0;
c = 0;
for (int i = 0;i < 10;i++){
temp = 0;
//count[num] == 0说明这个桶并没有保存数据
if (count[num] != 0){
//按照桶的索引将数据考入arr中
for (;temp < count[num];temp++){
arr[c++] = arrs[num][temp];
}
}
//清空原来每一个桶中数据的个数,使得桶可以重复使用
count[num] = 0;
num++;
}
n *= 10;
}
}
来源:CSDN
作者:qq_44637792
链接:https://blog.csdn.net/qq_44637792/article/details/104064155