总共需要进行n躺操作(1<=i<=n),每趟操作选出待排序的部分[i,n]中最小的元素,令其与A[i]交换。
从后面找出最小的,和前面的换
时间复杂度为O(n2)
空间复杂度 O(1)
不稳定
void selectSort()
{
for(int i=i;i<=n;i++){
int k=i;
for(int j=i;j<=n;j++){
if(A[j]<A[k]){
k=j;
}
}
int temp = A[i];
A[i] = A[k];
A[k]=temp;
}
}
void heapSort(int[] nums) {
int size = nums.length;
for (int i = size/2-1; i >=0; i--) {
adjust(nums, size, i);
}
for (int i = size - 1; i >= 1; i--) {
int temp = nums[0];
nums[0] = nums[i];
nums[i] = temp;
adjust(nums, i, 0);
}
}
void adjust(int []nums, int len, int index) {
int l = 2 * index + 1;
int r = 2 * index + 2;
int maxIndex = index;
if (l<len&&nums[l]>nums[maxIndex])maxIndex = l;
if (r<len&&nums[r]>nums[maxIndex])maxIndex = r;
if (maxIndex != index) {
int temp = nums[maxIndex];
nums[maxIndex] = nums[index];
nums[index] = temp;
adjust(nums, len, maxIndex);
}
}
void InsertSort( ElemType A[],int n)
{
int i,j;
for(int i=2;i<n;i++) //依次将2~n 的插入
if(A[i] < A[j-1]){ //小于,往前放
A[0] = A[i]; //复制为哨兵,A[0]不存放位置
for(int j=i-1;A[0]<A[j];j--) // 从后往前在有序列表找代插入位置
A[j+1]=A[j]; // 向后挪位
A[j+1]=A[0]; //复制到插入位置
}
}
void InsertSort( ElemType A[],int n)
{
int i,j,low,high,mid;
for(int i=2;i<n;i++) //依次将2~n 的插入
A[0] = A[i];
low = 1;high = i-1;
while(low <=high){
mid=(low+high)/2;
if(A[mid]>A[0}) high = mid-1;
else low = mid+1;
}
for(int j=i-1;j>=high+1;--j) // 从后往前在有序列表找代插入位置
A[j+1]=A[j]; // 向后挪位
A[high+1]=A[0]; //复制到插入位置
}
}
插入排序的改进版。为了减少数据的移动次数,在初始序列较大时
取较大的步长,通常取序列长度的一半,此时只有两个元素比较,交换一次;
之后步长依次减半直至步长为1,即为插入排序,由于此时序列已接近有序,故插入元素时数据移动的次数会相对较少,效率得到了提高。
空间复杂度O(1)
时间复杂度:通常认为是O(n1.5) 稳定性:不稳定
最坏情况下,时间复杂度 O(n2)
仅适用于线性表为顺序存储的情况
void ShellSort(ElemType A[],int n){
for(dk=n/2;dk>=1;dk=dk/2) //步长变化
for(i=dk+1;i<=n;++i)
if(A[i]<A[i-dk]){
A[0]=A[i]; //暂存在A[0]
for(j=i-dk;j>0&&A[0]<A[j];j-=dk) //记录后移查找插入位置
A[j+dk]=A[j];
A[j+dk]=A[0];
}
}
[L1,R1] [L2,R2]
i j
merge(int A[],int L1,int R1,int L2,int R2){
int i=L1,j=L2;
int temp[maxn],index = 0;
while(i<=R1&&j<=R2){
if(A[i]<A[j]){
temp[index++]=A[i++];
}else{
temp[index++]=A[j++];
}
}
while(i<=R1) temp[index++]=A[i++]; //将[L1,R1]中剩余的元素加入temp
while(j<=R2) temp[index++]=A[j++]; //将[L2,R2]中剩余的元素加入temp
for(int i=0;i<index;i++){ //将temp赋值回原数组
A[L1+i] = temp[i];
}
}
void mergeSort(int A[],int left,int right){
if(left<right){
int mid = left+(right-left)/2;
mergeSort(A,left,mid);
mergeSort(A,mid+1,right);
merge(A,left,mid,mid+1,right);
}
}
练习题 数组中的逆序对
void BubbleSort(vector<int>& nums,int n){
for(int i=0;i<n-1;i++) {
bool flag = false;
for(int j=n-1;j>i;j--) {
if(nums[j-1]>nums[j]){
swap(nums[j-1],nums[j]);
flag = true;
}
}
if(flag == false){
return ;
}
}
}
(1)根据内存缓存区大小,将外存上的文件分为若干长度为l的子文件
(2)依次读入内存并利用内部排序方法对它们进行排序
(3)将排序好的有序子文件重新写回外存,称这些 有序子文件为 归并段 或 顺串
(4)对这些归并段进行逐趟归并,使归并段(有序子文件)逐渐由小到大
(5)直至得到整个有序文件为止
r个初始归并段(总记录/内存工作区可容纳的记录数),做k路平衡归并,树的高度 logkr = 归并趟数
传统总的比较次数:[log2r] (n-1)(k-1)/[log2k]
在做m路平衡归并排序的过程中,为实现输入\内部归并\输出的并行处理,需要设置2m个输入缓存区和2个输出缓、存区