數據結構學習筆記之——排序
基本概念
排序:重新排列表中的元素,使表中的元素滿足按關鍵字遞增或遞減的過程。
算法的穩定性:如果待排序表中有兩個元素 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);
}
}