一、排序的概念
- 排序:所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。
- 稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排序算法是稳定的;否则称为不稳定的。
二、排序的常见算法
2.1 插入排序
- 直接插入排序是一种简单的插入排序法,其基本思想是:把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列
。实际中我们玩扑克牌时,就用了插入排序的思想
public static void insertSort(int[] array){
for(int i=1;i<array.length-1;i++){
int tmp=array[i];
int j=i-1;
for(j=i-1;j>=0;j--){
if(tmp<array[j]){
array[j+1]=array[j];
}else{
break;
}
}
array[j]=tmp;//无论是中途跳出还是最终结束,都要执行这一个步骤
}
}
2.2 希尔排序
- 希尔排序法又称缩小增量法。希尔排序法的基本思想是:先选定一个整数,把待排序文件中所有记录分成整数个组,所有距离为这个整数的记录分在同一组内,并对每一组内的记录进行排序。然后,组内进行插入排序,重复上述分组和排序的工作。当到达=1时,所有记录在统一组内排好序。
//2 希尔排序
public static void shellSort(int[] array){
int gap=array.length;
while(gap!=1){
gap=gap/2;
shell(array,gap);
}
shell(array,1);
}
private static void shell(int[] array,int gap){
for(int i=gap;i<array.length-1;i++){
int tmp=array[i];
int j=i-gap;
for(j=i-gap;j>=0;j=j-gap){//递减的数字
if(tmp<array[j]){
array[j+gap]=array[j];
}else{
break;
}
}
array[j]=tmp;//这里是j把
}
}
2.3 选择排序
- 每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元 素排完 。
//3 选择排序:只找最小元素
public static void selectSort1(int[] array){
for(int i=0;i<array.length-1;i++){
int min=array[i];
int j=i+1;
for(j=i+1;j<array.length-1;j++){
if(array[j]<min){
int tmp=array[j];
array[tmp]=array[j];
array[j]=tmp;
}
}
}
}
2.4 堆排序
- 堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。它是通过堆来进行选择数据。需要注意的是排升序要建大堆,排降序建小堆。
//5 堆排序:建立大根堆、交换、向下调整
public static void heapSort(int[] array){
createHeap(array);
int end=array.length-1;
while(end>0){
swap(array,0,end);
turnDown(array,0,end);
end--;
}
}
public static void createHeap(int[] array){
for(int parent=(array.length-1-1)/2;parent>=0;parent--){
int len=array.length;
turnDown(array,parent,len);
}
}
public static void turnDown(int[] array,int parent,int len){
int child=2*parent+1;
while(child<len){
if(child+1<len && array[child+1]>array[child]){
child=child+1;
}
if(array[child]>array[parent]){
swap(array,child,parent);
parent=child;
child=2*parent+1;
}else{
break;
}
}
}
2.5 冒泡排序
- 基本思想:所谓交换,就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置,交换排序的特点是:将键值较大的记录向序列的尾部移动,键值较小的记录向序列的前部移动。
//6 冒泡排序
public static void bubbleSort(int[] array){
for(int i=0;i<array.length-1;i++){
boolean flg=true;
for(int j=0;j<array.length-1-i;j++){
if(array[j]>array[j+1]){
swap(array,i,j+1);
flg=false;
}
}
if(flg==true){
break;
}
}
}
2.6 快速排序
- 其基本思想为:任取待排序元素序列中的某元
素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。
//7 快速排序hoare版
public static void quickSort(int[] array){
quick(array,0,array.length-1);
}
public static void quick(int[] array,int left,int right){
if(left>=right){
return;
}
int pilot=partition(array,left,right);
quick(array,left,pilot-1);
quick(array,pilot+1,right);
}
public static int partition(int[] array,int start,int end){
int i=start;
int key=array[start];
while(start<end){
while(start<end && array[end]>=key){
end--;
}
while(start<end && array[start]<=key){
start++;
}
swap(array,start,end);
}
swap(array,i,start);
return start;
}
2.7 归并排序
//11 归并排序
public static void mergeSort(int[] array,int left,int right){
int mid=(left+right)/2;
mergeSort(array,left,mid);
mergeSort(array,mid+1,right);//利用递归不断的分解
merge(array,left,right,mid);
}
private static void merge(int[] array,int start,int end,int midIndex){
int[] tmpArr=new int[end-start+1];
int k=0;
int s1=start;
int s2=midIndex+1;
//当合并的两个有序数组内部都是有元素的时候
while(s1<=midIndex && s2<=end){
if(array[s1]<array[s2]){
tmpArr[k++]=array[s1++];
}else{
tmpArr[k++]=array[s2++];
}
}
//判断跳出循环,是因为哪个数组走完了
while(s1<=midIndex){
tmpArr[k++]=array[s1++];
}
while(s2<=end){
tmpArr[k++]=array[s2++];
}
//把排序好的数字拷贝回原数组
for(int i=0;i<k;i++){
array[i+start]=tmpArr[i];
}
}
2.8 计数排序
- 思想:计数排序又称为鸽巢原理,是对哈希直接定址法的变形应用。 操作步骤:
- 统计相同元素出现次数
- 根据统计的结果将序列回收到原来的序列中
//13 计数排序:统计数组里面相同元素的出现次数
//比如:统计【101-120】之间的数字出现的次数
public static void countSort(int[] array){
int minVal=array[0];
int maxVal=array[0];
for(int i=0;i<array.length;i++){
if(array[i]<minVal){
minVal=array[i];
}
if(array[i]>maxVal){
maxVal=array[i];
}
}
int[] count=new int[maxVal-minVal+1];
for(int i=0;i<array.length;i++){
count[array[i]-minVal]++;
}
int index=0;
for(int i=0;i<count.length-1;i++){
while(count[i]!=0){
array[index++]=i+minVal;//实际上用元素大小表示下标,元素太大的话就减去最小值
count[i]--;
}
}
}