交换类排序
1.冒泡排序(n*n)
第一轮交换的区间 0~N-1,最大数放到第N-1位置
.1第一个数与第二数比较,谁大放后面,
.2.然后第二个数与第三个数比较,谁大放后面
.3.依次交换,最大的数放到数组最后面
第二轮交换区间0~N-2,最大数放大第N-2位置
…
最后一轮 确定第1位和第2位值
2.快速排序(n*logN)
第一步,随机找出一个数,通过比较比这数大的放右边,比该数小的放左边
第二步,递归对左右区间分别进行步骤一
第三步,左右区间只有一位数时候停止
void QSort(int A[],int low,int high)
//对数组A[low,...,high]
{
if(low<high)
{
int n;
n=Partition(A,low,high);
QSort(A,low,n-1);
QSort(A,n+1,high);
}
}
int Partition(int A[],int low,int high)
//交换数组A[low,...,high]的记录,支点记录到位,并返回其所在位置,此时
//在它之前(后)的记录均不大(小)于它
{
int key=A[low];
while(low<high)
{
while(low<high&&A[high]>=key)
high--;
A[low]=A[high];
while(low<high&&A[low]<=key)
low++;
A[high]=A[low];
}
A[low]=key;
return low;
}
选择类排序
1.直接选择排序(n*n)
第一轮选择区间0~N-1,选择出最小的值,放到位置0
第二轮选择区间1~N-1, 选择出最小的值,放到位置1
…
最后一轮区间N-2~N-1,最小的数(数组中最大的)放到位置N-1
2.堆排序(n*logN)
第一步:将无序序列构成一个堆,根据升序降序选择大根堆或小根堆
第二步:将堆顶元素与末尾元素交换,然后将最大元素沉到数组末端
第三步:此时重新调整堆结构(堆数量减一),执行第二步,直到堆中只剩下一个元素
构建堆的时间复杂度o(n) 循环n-1 次,每一次时间复杂度logN,总时间复杂度:nlogN-logN.
void Hsort(int[] arr){
for(int i=arr.length/2-1;i>=0;i--){//构建大根堆
adjustHeap(arr,i,arr.length);
}
for(int j=arr.length-1;j>0;j--){//堆首元素与推尾交换,剩下n-1继续构建大根堆,依次达到排序效果
swap(arr,0,j);
adjustHeap(arr,0,j);
}
}
void adjustHeap(int[] arr,int i,int length){
int temp = arr[i];
for(int k=i*2+1;k<length;k=k*2+1){//每次如果发生了当前结点与孩子结点的交换,则要考虑交换后的孩子结点(值被交换了)与其孩子结点是否满足堆定义
if(k+1<length && arr[k]<arr[k+1])
k++;
if(arr[k]>temp){//结点发生交换,循环继续,对交换后的孩子结点进行调整
arr[i]=arr[k];
i=k;
}else{break;}
arr[i]=temp;
}
归并类排序
1.归并排序(n*logN)
第一步,让数组中每一个数独立成为一个区间
第二步,相邻长度为一的区间进行合并,形成长度为2的有序序列
…
最后一步,将相邻长度n/2 的两个区间进行合并,形成长度为n的有序序列。
void sort(int[] arr,int left,int right,int []temp){
if(left<right){
int mid = (left+right)/2;
sort(arr,left,mid,temp);//左边归并排序,使得左子序列有序
sort(arr,mid+1,right,temp);//右边归并排序,使得右子序列有序
merge(arr,left,mid,right,temp);//将两个有序子数组合并操作
}
}
void merge(int[] arr,int left,int mid,int right,int[] temp){
int i = left;//左序列指针
int j = mid+1;//右序列指针
int t = 0;//临时数组指针
while (i<=mid && j<=right){
if(arr[i]<=arr[j]){
temp[t++] = arr[i++];
}else {
temp[t++] = arr[j++];
}
}
while(i<=mid){//将左边剩余元素填充进temp中
temp[t++] = arr[i++];
}
while(j<=right){//将右序列剩余元素填充进temp中
temp[t++] = arr[j++];
}
t = 0;
//将temp中的元素全部拷贝到原数组中
while(left <= right){
arr[left++] = temp[t++];
}
}
}
插入类排序
1.直接插入类排序(n*n)
第一次插入区间0~0,如果比0位置上元素小,放入到0位置。
第二次插入区间0-1,从1~0开始比较,直到找出小于位置2元素所在位置,插入到其后面.
…
最后一次插入区间0-N-2,从N-2~-0开始比较,直到找出小于位置N-1元素所在位置,插入到其后面。
2.希尔排序
第一轮,选择步长 gap1=N/2,对数组中的每一个元素,分别与前面第gap1 个元素做比较,如果比其小则交换,再与交换后位置的前第gap1个元素做比较,遇到越界则结束。
第二轮,选择步长gap2=gap1/2,操作过程同上
知道gap==1,做最后一次类似插入类排序实现整体排序。
总结
交换类排序,指的是满足某一条件即发生两个数发生交换,而这些条件往往而不需要考虑全局情况。比如冒泡排序中比相邻的大,快速排序中比特定值大。
选择类排序,同样满足某一个条件发生交换,这里的条件往往是全局的条件按,比如推排序中每次选择最小的/最大的值,直接选择排序每次选择最小的放左边。
插入类排序,可以任务是交换类排序的升级,满足条件后不是交换而是插入到某一个位子。