演算法與資料結構——排序
阿新 • • 發佈:2020-10-09
前提
void X_Sort (ElementType A[], int N) //預設討論從小到大的整數排序
-
氣泡排序
void Bubble_Sort(ElementType A[], int N) { for (int P = N - 1; P >= 0; P--) { int flag = 1; for (int i = 0; i < P; i++) { if (A[i] > A[i + 1]) { Swap(A[i], A[i + 1]); //交換兩數 flag = 1; } } if (flag == 0) break;//無交換則退出 } }
- 優點:比較穩定,不僅適用於陣列,而且適用於單向連結串列
-
插入排序
void Insert_Sort(ElementType A[], int N)
{
int i;
for (int p = 1; p < N; p++)
{
int Tmp = A[p];
for ( i = p; i > 0 && A[i - 1] > Tmp; i--)
{
A[i] = A[i - 1];
}
A[i] = Tmp;
}
}
優點:穩定
-
希爾排序
void Sheel_Sort(ElementType A[], int N) { int i; for (int D = N / 2; D > 0; D /= 2) //D為增量序列(此為最原始的希爾排序) { for (int P = D; P < N; P++) { int Tmp = A[P]; for ( i = P; i >= D && A[i - D] > Tmp; i -= D) { A[i] = A[i - D]; } A[i] = Tmp; } } }
增量序列D因情況而異,特殊情況下互質的增量序列是沒有效果的;
-
選擇排序
void Select_Sort(ElementType A[], int N) { int minid; for (int i = 0; i < N; i++) { minid = i; for (int j = i + 1; j < N - 1; j++) { if (A[j] < A[minid]) { minid = j; } } int tmp = A[i]; A[i] = A[minid]; A[minid] = tmp; } }
-
堆排序
-
歸併排序
-
遞迴實現
void merge(ElementType A[], ElementType tempArr[], int left, int mid, int right)
{
int L_pos = left;
int R_pos = mid + 1;
int pos = left;
while (L_pos <= mid && R_pos <= right)
{
if (A[L_pos] < A[R_pos])
{
tempArr[pos++] = A[L_pos++];
}
else
{
tempArr[pos++] = A[R_pos++];
}
}
while (L_pos <= mid)
{
tempArr[pos++] = A[L_pos++];
}
while (R_pos <= right)
{
tempArr[pos++] = A[R_pos++];
}
while (left <= right)
{
A[left] = tempArr[left];
left++;
}
}
void msort(ElementType A[], ElementType tempArr[], int left, int right)
{
if (left < right)
{
int mid = (left + right) / 2;
msort(A, tempArr, left, mid);
msort(A, tempArr, mid + 1, right);
merge(A, tempArr, left, mid, right);
}
}
void Merge_sort(ElementType A[], int N)
{
//分配一個輔助陣列
int* tempArr = (int*)malloc(N * sizeof(ElementType));
if (tempArr)
{
msort(A, tempArr, 0, N - 1);
free(tempArr);
}
else
{
printf("error: failed to allocate memory");
}
}
- 非遞迴演算法(迴圈實現)
/* 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[] */
}
void Merge_pass( ElementType A[], ElementType TmpA[], int N, int length )
{ /* 兩兩歸併相鄰有序子列 */
int i, j;
for ( i=0; i <= N-2*length; i += 2*length ) //只兩兩歸併到倒數第二組,尾巴的情況要單獨考慮
Merge( A, TmpA, i, i+length, i+2*length-1 );
if ( i+length < N ) /* 歸併最後2個子列*/
Merge( A, TmpA, i, i+length, N-1);
else /* 最後只剩1個子列*/
for ( j = i; j < N; j++ ) TmpA[j] = A[j];
}
void Merge_Sort( ElementType A[], int N )
{
int length;
ElementType *TmpA;
length = 1; /* 初始化子序列長度*/
TmpA = malloc( N * sizeof( ElementType ) );
if ( TmpA != NULL ) {
while( length < N ) {
//迴圈使用A[]和TmpA[],節省了Merge()函式中每次都要將TmpA中有序陣列複製回A的過程
Merge_pass( A, TmpA, N, length );
length *= 2;
Merge_pass( TmpA, A, N, length );
length *= 2;
}
free( TmpA );
}
else printf( "空間不足" );
}
未完待續。。。。。