前提
void X_sort(ElementType A[],int N);
稳定性:任意两个相等的数据,排序前后的相对位置不发生改变。
冒泡排序:一次一次的比较a[i]和a[i+1]的大小
void Bubble_sort (ElementTypr A[],int N)
{
for( P=N-1 ; P > 0 ; P-- )
{
flag = 0;//判断是否循环有没有变
for( i = 0 ; i < P ; i++ )
{
if( A[i] > A[i+1])
{
Swap(A[i],A[i+1]);
flag = 1 ;//进入循环,flag值变为1
}
}
if (flag == 0) break;//跳出循环
}
}
最好情况: T = O(N) 最坏情况: T = O(N^2)
插入排序:
可以理解为斗地主比手牌的顺序
void Insertion_sort (ElementType A[],int N)
{
for(P=1; P<N ; P++)
{
Tmp = A[P]; // 摸牌
for (i=p;i>0 && A[i-1] > Tmp ; i--) A[i] = A[i-1];//移出空位
A[i] = Tmp;
}
}
最好情况: 顺序T=O(N) 最坏情况:逆序T = O(N^2)
{
逆序对:对于下标 i<j,如果A[i] > A[j],则称(i,j)是一对逆序对
定理:任意N个不同元素组成的序列平均具有N(N-1)/4个逆序对。
定理:任何仅以交换相邻两元素来排序的算法,其平均时间复杂度为(下标)(N^2)
}
希尔排序:
1.定义增量序列Dn>D(n-1)>...>D1 = 1 最后间隔应该为1
2.对每个Dn 进行“ Dk - 间隔 ”排序(k = M,M-1, ... 1)
特点:
更小间隔的排序对于上一个间隔的排序任然有序
原始希尔排序(间隔取Dm=[N/2],Dk=[D(k+1) / 2])
void Shell_sort (ElementType A[],int N)
{
for( D=N/2 ; D>0 ; D/=2)
{ for(P=D ; P<N ; P++) Tmp = A[P]
{
for ( i=p ; i>=D && A[i-D]>Tmp ; i-=D ) A[i] = A[i-D];
A[i] = Tmp;
}
}
}
最坏情况 T = (N^2) ,排序一直都是顺序的,到最后只能靠间隔为1的插入排序
更多增量序列:
Hibbard增量序列 Dk=2^k - 1 (相邻元素护质) 最坏情况: T = (N^(3/2)) 猜想 Tavg = O(N^5/4)
Sedgewick增量序列 9*4^i - 9*2^i + 1 或 4^i - 3*2^i + 1 Tavg = O(N^7/2) Tworst = O(N^(4/3))
选择排序:
找到最小的值把它放在a[0]处,以此类推。
void Selection_sort (ElementType A[] , int N)
{
for (i = 0; i<N ; i++)
{
MinPosition = ScanForMin(A,i,N-1);
//从A[i]到A[N-1]中找最小元,并将其位置赋给MinPosition
Swap(A[i],A[MinPosition])
//将末排序部分的最小元换到有序部分的最后位置
}
}
无论如何: T = (N^2)
堆排序:
void Heap_Sort (ElementType A[],int N)
{
BuildHeap (A);//将一个函数直接排序为最小堆 //O(N)
for( i=0 ; i<N ; i++ )
TmpA[i] = DeleteMin(A) ; // 根节点 //O(logN)
for( i=0 ; i<N ; i++) //O(N)
A[i] = TmpA[i];
}
T(N) = O(NlogN) 复制也需要空间,额外需要O(N)
算法2
void Heap_Sort (ElementType A[],int N)
{
for( i = N/2 ; i>=0; i--)
PercDown (A,i,N);
for( i=N-1 ; i>0; i--)
{
Swap (&A[0],&A[i]);
PercDown(A,0,i);
}
}
归并序列:核心(有序子列的归并)
两个排好序的序列,两个指针,一个数组
/* 归并排序 - 递归实现 */
/* L = 左边起始位置, R = 右边起始位置, RightEnd = 右边终点位置*/
void Merge( ElementType A[], ElementType TmpA[], int L, int R, int RightEnd )
{ /* 将有序的A[L]~A[R-1]和A[R]~A[RightEnd]归并成一个有序序列 */
int LeftEnd, NumElements, Tmp;
int i;
LeftEnd = R - 1; /* 左边终点位置 */
Tmp = L; /* 有序序列的起始位置 */
NumElements = RightEnd - L + 1;
while( L <= LeftEnd && R <= RightEnd ) {
if ( A[L] <= A[R] )
TmpA[Tmp++] = A[L++]; /* 将左边元素复制到TmpA */
else
TmpA[Tmp++] = A[R++]; /* 将右边元素复制到TmpA */
}
while( L <= LeftEnd )
TmpA[Tmp++] = A[L++]; /* 直接复制左边剩下的 */
while( R <= RightEnd )
TmpA[Tmp++] = A[R++]; /* 直接复制右边剩下的 */
for( i = 0; i < NumElements; i++, RightEnd -- )
A[RightEnd] = TmpA[RightEnd]; /* 将有序的TmpA[]复制回A[] */
}