数据结构学习笔记之——排序
基本概念
排序:重新排列表中的元素,使表中的元素满足按关键字递增或递减的过程。
算法的稳定性:如果待排序表中有两个元素 i,j,其对应关键字 ki,kj,且在排序前 i 在 j 前面,如果使用某一排序算法排序后,i 仍然在 j 前面,则称这个排序算法是稳定的,否则称排序算法是不稳定的。(算法是否具有稳定性并不能衡量一个算法的优劣,它主要是对算法的性质进行描述)
插入排序
插入排序是一种简单直观的排序方法,其基本思想在于每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的子序列中,直到全部记录插入完成。
- 直接插入排序
void InsertSort(int a[],int n)
{
for(int i=2;i<=n;++i)
if(a[i]<a[i-1])
{
a[0]=a[i];
for(int j=i-1;a[0]<a[j];--j)
a[j+1]=a[j];
a[j+1]=a[0];
}
}
- 折半插入排序
void InsertSort(int a[],int n)
{
int low,high,mid;
for(int i=2;i<=n;i++)
{
a[0]=a[i];
low=1;
high=i-1;
while(low<=high)
{
mid=(low+high)/2;
if(a[0]<a[mid])//此处判断若为a[0]<=a[mid],则此算法不稳定
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];
}
}
- 希尔排序
void ShellSort(int a[],int n)
{
int dk;
for(dk=n/2;dk>=1;dk/=2)
for(int i=1+dk;i<=n;++i)
if(a[i]<a[i-dk])
{
a[0]=a[i];
for(int j=i-dk;a[0]<a[j];j-=dk)
a[j+dk]=a[j];
a[j+dk]=a[0];
}
}
交换排序
所谓交换,就是根据序列中两个元素关键字的比较结果来对换这两个记录在序列中的位置。
- 冒泡排序
void BubbleSort(int a[],int n)
{
bool flag;
for(int i=0;i<n-1;i++)
{
flag=true;
for(int j=n-1;j>i;--j)
if(a[j]<a[j-1])
{
swap(a[j],a[j-1]);
flag=false;
}
if(flag)
return;
}
}
- 快速排序
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;
}
void QuickSort(int a[],int low,int high)
{
if(low<high)
{
int pivotpos=Partition(a,low,high);
QuickSort(a,low,pivotpos-1);
QuickSort(a,pivotops+1,high);
}
}
选择排序
选择排序的基本思想是:每一趟(例如第i趟)在后面n-i+1(i=1,2,…,n-1)个待排序元素中选取关键字最小的元素,作为有序子序列的第i个元素,直到第n-1趟做完,待排序元素只剩下一个,就不用再选了。
- 简单选择排序
void SelectSort(int a[],int n)
{
int min;
for(int i=0;i<n-1;i++)
{
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]);
}
}
- 堆排序
void AdjustDown(int a[],int len,int k)
{
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 BuildMaxHeap(int a[],int len)
{
for(int k=len/2;k>0;--k)
AdjustDown(a,len,k);
}
void HeapSort(int a[],int len)
{
BuildMaxHeap(a,len);
for(int i=len;i>1;--i)
{
swap(a[i],a[1]);
AdjustDown(a,i-1,1);
}
}
归并排序
“归并”的含义是将两个或两个以上的有序表组合成一个新的有序表。假定待排序表含有n个记录,则可以看成是n个有序的子表,每个子表长度为1,然后两两归并,得到[n/2]个长度为2或1的有序表:再两两归并,……如此重复,直到合并成一个长度为n的有序表为止,这种排序方法称为2-路归并排序。
int *b=(int *)malloc((n+1)*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=low;i<=mid&&j<=high;++k)
{
if(b[i]<=b[j])
a[k]=b[i++];
else
a[k]=b[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)
{
mid=(low+high)/2;
MergeSort(a,low,mid);
MergeSort(a,mid+1,high);
Merge(a,low,mid,high);
}
}