第九章 排序
排序(sort):重新排序表中的元素,使表中的元素满足按关键字有序的过程。
稳定性:
稳定的:关键字相同的元素在排序之后相对位置不变。
排序算法:
内部排序:数据都都在内存中。关注算法时间、空间复杂度更低。
外部排序:数据太多,无法全部放入内存。 还需关注使读/写磁盘次数更少。
1. 直接插入排序
算法思想:每次将一个待排序的记录按其关键字大小插入到前面已排好序的子序列中,直到全部记录插入完成。
void InsertSort(int A[],int n)
{
int i,j,temp;
for(i=1;i<n;i++)
if(A[i]<A[i-1])
{
temp=A[i];
for(j=i-1;j>=0 && A[j]>temp;j--)
A[j+1]=A[j];
A[j+1]=temp;
}
}
2.折半插入排序:直接插入排序的优化。
思路:先用折半查找找到应该插入的位置,再移动元素。
时间复杂度:O(n^2)
void InsertSort(int A[],int n)
{
int i,j,low,high,mid;
for(i=2;i<=n;i++)
{
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(j=i-1;j>=high+1;j--)
A[j+1]=A[j];
A[high+1]=A[0];
}
}
3. 希尔排序:先追求表中元素部分有序,再逐渐逼近全局有序
void ShellSort(int A[],int n)
{
int d,i,j;
for(d=n/2;d>=1;d=d/2)
for(i=d+1;i<=n;i++)
if(A[i]<A[i-d])
{
A[0]=A[i];
for(j=i-d;j>0 && A[0]<A[j];j=j-d)
A[j+d]=A[j];
A[j+d]=A[0];
}
}
4. 冒泡排序
(1)从后往前冒泡
void swap(int &a,int &b)
{
int temp = a;
a=b;
b=temp;
}
void BubbleSort(int A[],int n)
{
for(int i=0;i<n-1;i++)
{ bool flag=false;
for(int j=n-1;j>i;j--)
{
if(A[j-1]>A[j])
{
swap(A[j-1],A[j]);
flag=true;
}
}
if(flag==false)
return;
}
}
(2)从前往后冒泡
void BubbleSort(int A[],int n)
{
for(int i=0;i<n-1;i++)
{ bool flag=false;
for(int j=0;j<n-1-i;j++)
{
if(A[j]>A[j+1])
{
swap(A[j],A[j+1]);
flag=true;
}
}
if(flag==false)
return;
}
}
5. 快速排序
void QuickSort(int A[],int low,int high)
{
if(low<high)
{
int pivotpos=Partition(A,low,high);
QuickSort(A,low,pivotpos-1);
QuickSort(A,pivotpos+1,high);
}
}
int Partition(int A[],int low,int high)
{
int pivot=A[low];
while(low<high)
{
while(low<high && A[high]>=pivot)
high--;
A[low]=A[high];
while(low<high && A[low]<=pivot)
low++;
A[high]=A[low];
}
A[low]=pivot;
return low;
}
6. 简单选择排序
void swap(int &a,int &b)
{
int temp=a;
a=b;
b=temp;
}
void SelectSort(int A[],int n)
{
for(int i=0;i<n-1;i++)
{
int min=i;
for(int j=i+1;j<n;j++)
if(A[j]<A[min])
min=j;
if(min!=i)
swap(A[i],A[min]);
}
}
7. 堆排序
(1)建立大根堆
void BuildMaxHeap(int A[],int len)
{
for(int i=len/2;i>0;i--)
HeadAdjust(A,i,len);
}
void HeadAdjust(int A[],int k,int len)
{
A[0]=A[k];
for(int i=2*k;i<=len;i*=2)
{
if(i<len && A[i]<A[i+1])
i++;
if(A[0]>=A[i])
break;
else
{
A[k]=A[i];
k=i;
}
}
A[k]=A[0];
}
(2)堆排序的完整逻辑——大顶堆得到的排序序列是递增的
void HeapSort(int A[],int len)
{
BuildMaxHeap(A,len);
for(int i=len;i>1;i--)
{
swap(A[i],A[1]);
HeadAdjust(A,1,i-1);
}
}
完整代码:
void BuildMaxHeap(int A[],int len)
{
for(int i=len/2;i>0;i--)
HeadAdjust(A,i,len);
}
void HeadAdjust(int A[],int k,int len)
{
A[0]=A[k];
for(int i=2*k;i<=len;i*=2)
{
if(i<len && A[i]<A[i+1])
i++;
if(A[0]>=A[i])
break;
else
{
A[k]=A[i];
k=i;
}
}
A[k]=A[0];
}
void HeapSort(int A[],int len)
{
BuildMaxHeap(A,len);
for(int i=len;i>1;i--)
{
swap(A[i],A[1]);
HeadAdjust(A,1,i-1);
}
}
8. 归并排序
int *B=(int *)malloc(sizeof(int));
void Merge(int A[],int low,int mid,int high)
{
int i,j,k;
for(k=low;k<=high;k++)
B[k]=A[k];
for(i=low,j=mid+1,k=i;i<=mid&&j<=high;k++)
{
if(B[i]<=B[j])
{
A[k]=B[i];
i++;
}
else
{
A[k]=A[j];
j++;
}
}
while(i<=mid)
A[k++]=B[i++];
while(j<=high)
A[k++]=B[j++];
}
void MergeSort(int A[],int low,int high)
{
if(low<high)
{
int mid=(low+high)/2;
MergeSort(A[],low,mid);
MergeSort(A[],mid+1,high);
Merge(A[],low,mid,high);
}
}