目录
排序是指根据某一特定标准,将一组“无序”的数据元素调整为“有序”的数据元素的过程。排序是计算机内经常进行的一种操作,其目的是按照一定的规则(如数字大小、字母顺序等)对数据元素进行重新排列,以便更有效地进行搜索、比较和其他数据处理操作。
常见的排序方法有7种,直接插入排序,希尔排序,选择排序,堆排序,冒泡排序,快速排序,归并排序。
先定义一个交换的方法:
public static void Swap(int[]array,int i,int j){
int tmp=array[i];
array[i]=array[j];
array[j]=tmp;
}
一、直接插入排序
直接插入排序逻辑:
从一组数据的第二个元素开始,依次和前面的元素进行比较,找到合适的位置进行插入。
代码如下:
public static void insertSort(int[]array){
for (int i = 1; i < array.length; i++) {
int tmp=array[i];
int j=i-1;
for (; j >=0 ; j--) {
if (array[j]>tmp){
array[j+1]=array[j];
}else {
break;
}
}
array[j+1]=tmp;
}
}
二、希尔排序
希尔排序的逻辑:
希尔排序是对直接插入排序的优化,先把数据分组进行预排序,然后再整体排序,可以让排序速度加快。
代码如下:
public static void shellSort(int[]array){
//分组
int gap=array.length;
while (gap>1){
gap/=2;
shell(array,gap);
}
}
//排序
private static void shell(int[] array, int gap) {
for (int i = gap; i < array.length; i++) {
int tmp = array[i];
int j = i - gap;
for (; j >= 0; j-=gap) {
if (array[j] > tmp) {
array[j + gap] = array[j];
} else {
break;
}
}
array[j + gap] = tmp;
}
}
三、选择排序
选择排序有单向选择排序和双向选择排序。
单向选择排序逻辑:
对数组进行遍历,找到数组中最小的值,将最小值放到数组最前面,然后再找到除这个值之外的最小值放到上一个最小值的后面,以此类推遍历整个数组。
代码如下:
public static void selectSort(int[]array){
for (int i = 0; i < array.length; i++) {
int mindex=i;
for (int j = i+1; j < array.length; j++) {
if (array[j]<array[mindex]){
mindex=j;
}
}
Swap(array,i,mindex);
}
}
双向选择排序逻辑:
对数组进行遍历,找到数组中的最大值和最小值,将它放在数组的最前面和最后面,然后对剩下数据再进行同样的操作。
代码如下:
public static void DselectSort(int[]array){
int left=0;
int right=array.length-1;
while (left<right){
int minIndex=left;
int maxIndex=left;
for (int i = left+1; i <=right; i++) {
if (array[i] < array[minIndex]) {
minIndex = i;
}
if (array[i] > array[maxIndex]) {
maxIndex = i;
}
}
Swap(array,minIndex,left);
if (maxIndex==left){
maxIndex=minIndex;
}
Swap(array,maxIndex,right);
left++;
right--;
}
}
四、堆排序
堆排序逻辑:
创建一个大根堆,堆顶元素是最大的,让最大值的元素和最后一个元素进行互换,最大值的元素就被移到了最后,然后把其余元素再排成大根堆,将这次堆顶最大值元素和倒数第二个元素进行互换,以此类推,遍历整个大根堆。
代码如下:
//创建大根堆
public static void createHeap(int[]array){
for (int parent = (array.length-1-1)/2; parent >=0; parent--) {
siftDown(array,parent,array.length);
}
}
//向下调整
private static void siftDown(int[]array, int parent, int length) {
int child = 2 * parent + 1;
while (child < length) {
if (child + 1 < length && array[child] < array[child + 1]) {
child = child + 1;
}
if (array[child] > array[parent]) {
Swap(array, child, parent);
parent = child;
child = 2 * parent + 1;
} else {
break;
}
}
}
//堆排序
public static void heapSort (int[] array){
createHeap(array);
int end = array.length - 1;
while (end > 0) {
Swap(array, 0, end);
siftDown(array, 0, end);
end--;
}
}
五、冒泡排序
冒泡排序的逻辑:
遍历一组数据,从第一个值开始往后进行遍历,如果顺序错误就进行交换。
代码如下:
public static void bobbleSort(int[]array){
for (int i = 0; i < array.length-1; i++) {
boolean flag=false;
for (int j = 0; j < array.length-i-1; j++) {
if (array[j]>array[j+1]){
Swap(array,j,j+1);
flag=true;
}
}
if (flag==false){
break;
}
}
}
六、快速排序
快速排序的逻辑:
在数组中,以第一个值为基准,从后往前找到比基准小的值,然后从前往后找到比基准大的值,然后将这两个值进行交互,当从后往前找和从前往后找相遇时,将相遇的值和基准值进行交换,然后再对数组进行递归。
代码如下:
public static void quickSort(int[]array){
quick(array,0,array.length-1);
}
//快速排序
private static void quick(int[]array,int start,int end){
if (start>=end){
return;
}
int pivot=partitionHoare(array,start,end);
quick(array,start,pivot-1);
quick(array,pivot+1,end);
}
private static int partitionHoare(int[]array,int left,int right){
int tmp=array[left];
int i=left;
while (left<right){
while (left<right&&array[right]>=tmp){
right--;
}
while (left<right&&array[left]<=tmp){
left++;
}
Swap(array,left,right);
}
Swap(array,i,left);
return left;
}
七、归并排序
归并排序的逻辑:
将数组进行不断拆分,拆分到只有一个元素时,然后对元素进行有序的组合。
代码如下:
public static void mergeSort(int[]array){
mergeSortFun(array,0,array.length-1);
}
private static void mergeSortFun(int[] array, int start, int end) {
if (start>=end){
return;
}
int mid=(start+end)/2;
mergeSortFun(array,start,mid);
mergeSortFun(array,mid+1,end);
merge(array,start,mid,end);
}
private static void merge(int[] array, int left, int mid, int right) {
int s1=left;
int e1=mid;
int s2=mid+1;
int e2=right;
int[]tmpArr=new int[right-left+1];
int k=0;
while (s1<=e1&&s2<=e2){
if (array[s1]<=array[s2]){
tmpArr[k++]=array[s1++];
}else {
tmpArr[k++]=array[s2++];
}
}
while (s1<=e1){
tmpArr[k++]=array[s1++];
}
while (s2<=e2){
tmpArr[k++]=array[s2++];
}
for (int i = 0; i < tmpArr.length; i++) {
array[i+left]=tmpArr[i];
}
}