數據結構 排序【簡單排序(冒泡、插入)、希爾排序、堆排序、排序方法的綜合比較、2套 排序彙總代碼】

目   錄

第9章 排序(上)

9.1 簡單排序(冒泡、插入)

1、前提

2、簡單排序(冒泡排序)

3、簡單排序(插入排序)

4、時間複雜度下界

9.2 希爾排序

9.3 堆排序

排序方法綜合比較

排序彙總(1)

排序彙總(2)


第9章 排序(上)

9.1 簡單排序(冒泡、插入)

1、前提

void X_Sort ( ElementType A[], int N )

  1. 大多數情況下,爲簡單起見,討論從小大的整數排序
  2. N是正整數
  3. 只討論基於比較的排序(> = < 有定義)
  4. 只討論內部排序
  5. 穩定性:任意兩個相等的數據, 排序前後的相對位置不發生改變
  6. 沒有一種排序是任何情況下 都表現最好的

ElemnetType:所排元素類型;N:元素個數。10萬數據量。

2、簡單排序(冒泡排序)

void Bubble_Sort( ElementType 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; /* 標識發生了交換 */
            }
        }
        if ( flag==0 ) 
            break; /* 全程無交換 */
    }
}

冒泡排序 優點:對 數組、鏈表,均可進行排序。

P=N-1:從最後的元素,開始往前比較。

對於7個數進行冒泡排序,最壞情況下需要進行的比較次數爲 21 .

3、簡單排序(插入排序)

void InsertionSort( ElementType A[], int N )
{ /* 插入排序 */
     int P, i;
     ElementType Tmp;
      
     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; /* 放進合適的位置 */
     }
}

 P=1:初始手中 就有 1張牌。

給定初始序列{34, 8, 64, 51, 32, 21},冒泡排序和插入排序分別需要多少次元素交換才能完成?【冒泡9次,插入9次】

對一組包含10個元素的非遞減有序序列,採用插入排序排成非遞增序列,其可能的比較次數和移動次數分別是【45, 44】。

4、時間複雜度下界

序列{34, 8, 64, 51, 32, 21}中有多少逆序對?【9】 

N:元素個數;I:逆序對個數。

9.2 希爾排序

void ShellSort( ElementType A[], int N )
{ /* 希爾排序 - 用Sedgewick增量序列 */
     int Si, D, P, i;
     ElementType Tmp;
     /* 這裏只列出一小部分增量 */
     int Sedgewick[] = {929, 505, 209, 109, 41, 19, 5, 1, 0};
      
     for ( Si=0; Sedgewick[Si]>=N; Si++ ); 
     /* 初始的增量Sedgewick[Si]不能超過待排序列長度 */
 
     for ( D=Sedgewick[Si]; D>0; D=Sedgewick[++Si] )
         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;
         }
}

希爾排序是穩定的。【錯誤】

9.3 堆排序

void Swap( ElementType *a, ElementType *b )
{
     ElementType t = *a; *a = *b; *b = t;
}
  
void PercDown( ElementType A[], int p, int N )
{ /* 改編代碼4.24的PercDown( MaxHeap H, int p )    */
  /* 將N個元素的數組中以A[p]爲根的子堆調整爲最大堆 */
    int Parent, Child;
    ElementType X;
 
    X = A[p]; /* 取出根結點存放的值 */
    for( Parent=p; (Parent*2+1)<N; Parent=Child ) {
        Child = Parent * 2 + 1;
        if( (Child!=N-1) && (A[Child]<A[Child+1]) )
            Child++;  /* Child指向左右子結點的較大者 */
        if( X >= A[Child] ) break; /* 找到了合適位置 */
        else  /* 下濾X */
            A[Parent] = A[Child];
    }
    A[Parent] = X;
}
 
void HeapSort( ElementType A[], int N ) 
{ /* 堆排序 */
     int i;
       
     for ( i=N/2-1; i>=0; i-- )/* 建立最大堆 */
         PercDown( A, i, N );
      
     for ( i=N-1; i>0; i-- ) {
         /* 刪除最大堆頂 */
         Swap( &A[0], &A[i] ); /* 見代碼7.1 */
         PercDown( A, 0, i );
     }
}
typedef struct HNode *Heap; /* 堆的類型定義 */

struct HNode {

    ElementType *Data; /* 存儲元素的數組 */

    int Size;          /* 堆中當前元素個數 */

    int Capacity;      /* 堆的最大容量 */

};

typedef Heap MaxHeap; /* 最大堆 */

typedef Heap MinHeap; /* 最小堆 */

 

#define MAXDATA 1000  /* 該值應根據具體情況定義爲大於堆中所有可能元素的值 */

 

MaxHeap CreateHeap( int MaxSize )

{ /* 創建容量爲MaxSize的空的最大堆 */

 

    MaxHeap H = (MaxHeap)malloc(sizeof(struct HNode));

    H->Data = (ElementType *)malloc((MaxSize+1)*sizeof(ElementType));
    //指向數組,下標從1開始,所以 是 MaxSize+1

    H->Size = 0;

    H->Capacity = MaxSize;

    H->Data[0] = MAXDATA; /* 定義"哨兵"爲大於堆中所有可能元素的值*/

 

    return H;

}

 

bool IsFull( MaxHeap H )

{

    return (H->Size == H->Capacity);

}

 

bool Insert( MaxHeap H, ElementType X )

{ /* 將元素X插入最大堆H,其中H->Data[0]已經定義爲哨兵 */

    int i;

  

    if ( IsFull(H) ) { 

        printf("最大堆已滿");

        return false;

    }

    i = ++H->Size; /* i指向插入後堆中的最後一個元素的位置 */

    for ( ; H->Data[i/2] < X; i/=2 )

        H->Data[i] = H->Data[i/2]; /* 上濾X */

    H->Data[i] = X; /* 將X插入 */

    return true;

}

 

#define ERROR -1 /* 錯誤標識應根據具體情況定義爲堆中不可能出現的元素值 */

 

bool IsEmpty( MaxHeap H )

{

    return (H->Size == 0);

}

 

ElementType DeleteMax( MaxHeap H )

{ /* 從最大堆H中取出鍵值爲最大的元素,並刪除一個結點 */

    int Parent, Child;

    ElementType MaxItem, X;

 

    if ( IsEmpty(H) ) {

        printf("最大堆已爲空");

        return ERROR;

    }

 

    MaxItem = H->Data[1]; /* 取出根結點存放的最大值 */

    /* 用最大堆中最後一個元素從根結點開始向上過濾下層結點 */

    X = H->Data[H->Size--]; /* 注意當前堆的規模要減小 */

    for( Parent=1; Parent*2<=H->Size; Parent=Child ) {

        Child = Parent * 2;

        if( (Child!=H->Size) && (H->Data[Child]<H->Data[Child+1]) )

            Child++;  /* Child指向左右子結點的較大者 */

        if( X >= H->Data[Child] ) break; /* 找到了合適位置 */

        else  /* 下濾X */

            H->Data[Parent] = H->Data[Child];

    }

    H->Data[Parent] = X;

 

    return MaxItem;

} 

 

/*----------- 建造最大堆 -----------*/

void PercDown( MaxHeap H, int p )

{ /* 下濾:將H中以H->Data[p]爲根的子堆調整爲最大堆 */

    int Parent, Child;

    ElementType X;

 

    X = H->Data[p]; /* 取出根結點存放的值 */

    for( Parent=p; Parent*2<=H->Size; Parent=Child ) {

        Child = Parent * 2;

        if( (Child!=H->Size) && (H->Data[Child]<H->Data[Child+1]) )

            Child++;  /* Child指向左右子結點的較大者 */

        if( X >= H->Data[Child] ) break; /* 找到了合適位置 */

        else  /* 下濾X */

            H->Data[Parent] = H->Data[Child];

    }

    H->Data[Parent] = X;

}

 

void BuildHeap( MaxHeap H )

{ /* 調整H->Data[]中的元素,使滿足最大堆的有序性  */

  /* 這裏假設所有H->Size個元素已經存在H->Data[]中 */


    int i;


    /* 從最後一個結點的父節點開始,到根結點1 */

    for( i = H->Size/2; i>0; i-- )

        PercDown( H, i );

}

有個堆其元素在數組中的序列爲:58,25,44,18,10,26,20,12。如果調用DeleteMax函數刪除最大值元素,請猜猜看:程序中的for循環剛退出時變量parent的值是多少?【6】

 

建堆時,最壞情況下需要挪動元素次數是等於樹中各結點的高度和。問:對於元素個數爲12的堆,其各結點的高度之和是多少?【10】

 

在堆排序中,元素下標從0開始。則對於下標爲i的元素,其左、右孩子的下標分別爲:【2i+1, 2i+2】

排序方法綜合比較

排序彙總(1)

#include <stdio.h>
#include <string.h>
#define MAXSIZE 100 /*參加排序元素的最大個數*/

/******************冒泡排序********************/
void maopao()
{
    int nums[MAXSIZE];
    int i, j, n, temp;
    int comnum = 0, movnum = 0;
    int num = 1;

    printf("您已進入冒泡排序\n");
    printf("請輸入排序序列長度:");
    scanf("%d", &n);
    printf("請輸入排序序列:");
    for (i = 0; i < n; i++)
        scanf("%d", &nums[i]);

    for (i = 0; i < n - 1; i++)
    {
        for (j = 0; j < n - i - 1; j++)
        {
            comnum++;
            if (nums[j] > nums[j + 1])
            {

                temp = nums[j];
                nums[j] = nums[j + 1];
                nums[j + 1] = temp;
                movnum++;
            }
        }

        printf("第%d趟排序結果:", num++);
        for (j = 0; j < n; j++)
        {
            printf("%d ", nums[j]);
        }
        printf("\n");
    }
    printf("排序過程比較次數:%d\n排序過程移動次數:%d\n", comnum, movnum);
    printf("\n");

    return;
}
/************************************************/

/*****************折半插入排序*******************/
void zheban()
{
    int nums[MAXSIZE];
    int i, j, n, temp;
    int low, high, middle;
    int comnum = 0, movnum = 0;
    int num = 1;

    printf("您已進入折半插入排序\n");
    printf("請輸入排序序列長度:");
    scanf("%d", &n);
    printf("請輸入排序序列:");
    for (i = 0; i < n; i++)
    {
        scanf("%d", &nums[i]);
    }

    for (i = 1; i < n; i++)
    {
        low = 0;        //有序數組的開頭下標
        high = i - 1;   //有序數組的末尾下標
        temp = nums[i]; //要被插入的數
        middle = 0;
        //查找要被插入的下標
        while (low <= high)
        {
            middle = (low + high) / 2;
            if (temp < nums[middle])
            {
                high = middle - 1;
            }
            else
            {
                low = middle + 1;
            }
            comnum++;
        }
        //所有數右移,移完之後插入目標數
        for (j = i; j > low; j--)
        {
            nums[j] = nums[j - 1];
        }
        //交換nums[i]與nums[low]的位置
        nums[low] = temp;
        movnum++;

        printf("第%d趟排序結果:", num++);
        for (j = 0; j < n; j++)
        {
            printf("%d ", nums[j]);
        }
        printf("\n");
    }
    printf("排序過程比較次數:%d\n排序過程移動次數:%d\n", comnum, movnum);
    printf("\n");

    return;
}
/************************************************/

/*******************希爾排序*********************/
void shell()
{
    int i, j, k, n, dk, temp;
    int nums[MAXSIZE];
    int comnum = 0, movnum = 0;
    int num = 1;

    printf("您已進入希爾排序\n");
    printf("請輸入排序序列長度:");
    scanf("%d", &n);
    printf("請輸入排序序列:");
    for (i = 0; i < n; i++)
    {
        scanf("%d", &nums[i]);
    }

    for (dk = n / 2; dk > 0; dk = dk / 2)
    {
        for (i = 0; i < dk; i++)
        {
            for (j = i + dk; j < n; j = j + dk)
            { //單獨一次的插入排序
                if (nums[j] < nums[j - dk])
                {
                    temp = nums[j]; //哨兵
                    k = j - dk;
                    while (k >= 0 && nums[k] > temp)
                    {
                        nums[k + dk] = nums[k];
                        k = k - dk;
                    }
                    nums[k + dk] = temp;
                    movnum++;
                }
                comnum++;
            }
        }
        printf("第%d趟排序結果:", num++);
        for (i = 0; i < n; i++)
        {
            printf("%d ", nums[i]);
        }
        printf("\n");
    }
    printf("排序過程比較次數:%d\n排序過程移動次數:%d\n", comnum, movnum);
    printf("\n");

    return;
}
/************************************************/

/*******************快速排序*********************/
int CN = 0;
int MN = 0;
int T = 1;
void Fswap(int nums[], int i, int j)
{
    int temp;
    temp = nums[i];
    nums[i] = nums[j];
    nums[j] = temp;
    MN++;
}

int partition(int nums[], int low, int high, int n)
{
    int i;
    int pivotkey;
    pivotkey = nums[low];
    while (low < high) //以pivoekey爲軸,將大於它的放在後邊,小於它的放在前面
    {
        while (low < high && nums[high] >= pivotkey) //條件判斷 low < high
        {
            high--;
            CN++;
        }
        Fswap(nums, low, high);
        while (low < high && nums[low] <= pivotkey)
        {
            low++;
            CN++;
        }
        Fswap(nums, low, high);

        printf("第%d趟排序結果:", T++);
        for (i = 0; i < n; i++)
        {
            printf("%d ", nums[i]);
        }
        printf("\n");
    }
    return low; //返回樞軸所在位置
}

void quickSort(int nums[], int low, int high, int n)
{
    int pivot;
    if (low < high)
    {
        pivot = partition(nums, low, high, n); //將nums[]一分爲二

        quickSort(nums, low, pivot - 1, n);  //對低子表遞歸排序
        quickSort(nums, pivot + 1, high, n); //對高子表遞歸排序
    }
}

void kuaipai()
{
    int i, n;
    int nums[MAXSIZE];

    printf("您已進入快速排序\n");
    printf("請輸入排序序列長度:");
    scanf("%d", &n);
    printf("請輸入排序序列:");
    CN = 0;
    MN = 0;
    T = 1;

    for (i = 0; i < n; i++)
    {
        scanf("%d", &nums[i]);
    }

    quickSort(nums, 0, n - 1, n);

    printf("排序過程比較次數:%d\n排序過程移動次數:%d\n", CN, MN);
    printf("\n");

    return;
}
/************************************************/

/********************堆排序**********************/
int HCN = 0;
int HMN = 0;
int H = 1;
void HeapAdjust(int nums[], int s, int n)
{
    int i, j;
    int temp;

    for (i = s; 2 * i + 1 < n; i = j)
    {
        j = 2 * i + 1;
        if ((j < n - 1) && (nums[j] < nums[j + 1]))
        {
            j++;
            HCN++;
        }
        if (nums[i] < nums[j])
        {
            temp = nums[i];
            nums[i] = nums[j];
            nums[j] = temp;
            HCN++;
            HMN++;
        }
        else
            break;
    }
}

//堆排序
void HeapSort(int nums[], int n)
{
    int i, j;
    int temp;

    for (i = n / 2 - 1; i >= 0; i--)
    {
        HeapAdjust(nums, i, n);
        printf("第%d趟排序結果:", H++);
        for (j = 0; j < n; j++)
        {
            printf("%d ", nums[j]);
        }
        printf("\n");
    }
    for (i = n - 1; i > 0; i--)
    {
        temp = nums[i];
        nums[i] = nums[0];
        nums[0] = temp;
        HMN++;

        HeapAdjust(nums, 0, i);
        printf("第%d趟排序結果:", H++);
        for (j = 0; j < n; j++)
        {
            printf("%d ", nums[j]);
        }
        printf("\n");
    }
}

void duipai()
{
    int i, n;
    int nums[MAXSIZE];

    printf("您已進入堆排序\n");
    printf("請輸入排序序列長度:");
    scanf("%d", &n);
    printf("請輸入排序序列:");
    HMN = 0;
    HCN = 0;
    H = 1;

    for (i = 0; i < n; i++)
    {
        scanf("%d", &nums[i]);
    }

    HeapSort(nums, n);
    printf("排序過程比較次數:%d\n排序過程移動次數:%d\n", HCN, HMN);
    printf("\n");

    return;
}
/************************************************/

/*****************直接插入排序*******************/
void zhicha()
{
    int nums[MAXSIZE];
    int i, j, n;
    int temp;
    int comnum = 0, movnum = 0;
    int num = 1;

    printf("您已進入直接插入排序\n");
    printf("請輸入排序序列長度:");
    scanf("%d", &n);
    printf("請輸入排序序列:");
    for (i = 0; i < n; i++)
    {
        scanf("%d", &nums[i]);
    }

    for (i = 1; i < n; i++)
    {
        if (nums[i] < nums[i - 1])
        {
            temp = nums[i];
            for (j = i - 1; j >= 0; j--)
            {
                if (temp < nums[j])
                {
                    nums[j + 1] = nums[j];
                    comnum++;
                }
                else
                {
                    break;
                    comnum++;
                }
            }
            nums[j + 1] = temp;
            movnum++;
        }
        else
        {
            comnum++;
            continue;
        }

        printf("第%d趟排序結果:", num++);
        for (j = 0; j < n; j++)
        {
            printf("%d ", nums[j]);
        }
        printf("\n");
    }
    printf("排序過程比較次數:%d\n排序過程移動次數:%d\n", comnum, movnum);
    printf("\n");
}
/************************************************/

/*****************簡單選擇排序*******************/
void jiandan()
{
    int nums[MAXSIZE];
    int i, j, n;
    int temp, t;
    int comnum = 0, movnum = 0;
    int num = 1;

    printf("您已進入簡單選擇排序\n");
    printf("請輸入排序序列長度:");
    scanf("%d", &n);
    printf("請輸入排序序列:");
    for (i = 0; i < n; i++)
    {
        scanf("%d", &nums[i]);
    }

    for (i = 0; i < n; i++)
    {
        temp = nums[i];
        t = i;
        for (j = i + 1; j < n; j++)
        {
            if (nums[j] < temp)
            {
                temp = nums[j];
                t = j;
            }
            comnum++;
        }
        temp = nums[i];
        nums[i] = nums[t];
        nums[t] = temp;
        movnum++;

        printf("第%d趟排序結果:", num++);
        for (j = 0; j < n; j++)
        {
            printf("%d ", nums[j]);
        }
        printf("\n");
    }
    printf("排序過程比較次數:%d\n排序過程移動次數:%d\n", comnum, movnum);
    printf("\n");
}
/************************************************/

/********************主函數**********************/
int main()
{
    int n;

    while (1)
    {
        printf("    主菜單\n");
        printf("請選擇排序算法\n");
        printf("冒泡排序法       1\n");
        printf("折半插入排序法   2\n");
        printf("希爾排序法       3\n");
        printf("快速排序法       4\n");
        printf("堆排序法         5\n");
        printf("直接插入排序法   6\n");
        printf("簡單選擇排序法   7\n");
        printf("退出             0\n");
        scanf("%d", &n);
        switch (n)
        {
        case 1:
            maopao();
            continue;
        case 2:
            zheban();
            continue;
        case 3:
            shell();
            continue;
        case 4:
            kuaipai();
            continue;
        case 5:
            duipai();
            continue;
        case 6:
            zhicha();
            continue;
        case 7:
            jiandan();
            continue;
        default:
            break;
        }
        if (n == 0)
            break;
    }

    return 0;
}

排序彙總(2)

#include <iostream>
#include <stdio.h>
#include <stdlib.h>

using namespace std;

#ifndef SQLIST_H_INCLUDED
#define SQLIST_H_INCLUDED

#define MAXSIZE 20   //順序表的最大長度
typedef int KeyType; //定義關鍵字類型爲整型
typedef int InfoType;

typedef struct
{
    KeyType key;
    InfoType otherinfp;
} RedType;

typedef struct
{
    RedType r[MAXSIZE + 1]; //r[0]是哨兵的位置,防止數組越界
    int length;
} SqList;

void menu();
void InSqList(SqList &sq);
void InsertSort(SqList &sq);

void OutPrintSqList(SqList &L);

void BInsertSort(SqList &L);                //折半插入排序
void ShellSort(SqList &L, int dk[], int t); //希爾排序
void ShellInsert(SqList &L, int dk);        //做一趟增量爲dk的希爾排序
void BubbleSort(SqList &L);                 //冒泡排序

int PartitionQ(SqList &L, int low, int high); //一趟快速排序,返回樞軸位置
void QSort(SqList &L, int low, int high);
void QuickSort(SqList &L); //快速排序

void SelectSort(SqList &L); //簡單選擇排序

//堆排序
void HeapAdjust(SqList &L, int s, int m);
void CreateHeap(SqList &L);
void HeapSort(SqList &L);

//歸併排序
void Merge(SqList R, SqList &T, int low, int mid, int high);
void Msort(SqList R, SqList &T, int low, int high);
void MergeSort(SqList &L);
#endif // SQLIST_H_INCLUDED

void menu()
{
    printf("---------------------------\n");
    printf("1---直接插入排序\n");
    printf("2---折半插入排序\n");
    printf("3---希爾排序\n");
    printf("4---冒泡排序\n");
    printf("5---快速排序\n");
    printf("6---簡單選擇排序\n");
    printf("7---堆排序\n");
    printf("8---歸併排序\n");
    printf("0----退出\n");
    printf("----------------------------\n");
}

void InSqList(SqList &sq)
{
    int i = 1;
    sq.length = 0;
    printf("請輸入8個關鍵字:\n");
    for (; i <= 8; i++)
    {
        printf("請輸入第%d個關鍵字:\n", i);
        scanf("%d", &sq.r[i].key);
        sq.r[i].otherinfp = i;
        sq.length++;
    }
}

void OutPrintSqList(SqList &sq)
{
    int i;
    printf("******************\n");
    for (i = 1; i <= sq.length; i++)
        printf("%d ", sq.r[i].key);
    printf("\n");
}

void InsertSort(SqList &L)
{
    int i, j;
    for (i = 2; i <= L.length; i++)
    {
        if (L.r[i].key < L.r[i - 1].key)
        {
            L.r[0] = L.r[i];
            L.r[i] = L.r[i - 1];
            for (j = i - 2; L.r[0].key < L.r[j].key; j--)
                L.r[j + 1] = L.r[j];
            L.r[j + 1] = L.r[0];
        }
    }
}

void BInsertSort(SqList &L)
{
    int i, j, low, high, mid;
    for (i = 2; i <= L.length; i++)
    {
        L.r[0] = L.r[i];
        low = 1;
        high = i - 1;
        while (low <= high)
        {
            mid = (low + high) / 2;
            if (L.r[0].key < L.r[mid].key)
                high = mid - 1;
            else
                low = mid + 1;
        }

        for (j = i - 1; j >= high + 1; --j)
            L.r[j + 1] = L.r[j];
        L.r[j + 1] = L.r[0];
    }
}

void ShellSort(SqList &L, int dk[], int t) //希爾排序
{
    int k;
    for (k = 0; k < t; k++)
        ShellInsert(L, dk[k]);
}

//做一趟增量爲dk的希爾排序
void ShellInsert(SqList &L, int dk)
{
    int i, j;
    for (i = dk + 1; i <= L.length; i++)
    {
        if (L.r[i].key < L.r[i - dk].key) //需要將L.r[i]插入到有序增量子表
        {
            L.r[0] = L.r[i];                                            //暫存在L.r[0]
            for (j = i - dk; j > 0 && L.r[0].key < L.r[j].key; j -= dk) //記錄後移,直到找到插入位置
                L.r[j + dk] = L.r[j];
            L.r[j + dk] = L.r[0]; //將r[0]即原r[i],插入到正確位置
        }
    }
}

//冒泡排序
void BubbleSort(SqList &L)
{
    int j, i, flag = 1;
    RedType t;
    j = L.length - 1;

    while (j > 0 && flag == 1)
    {
        flag = 0;
        for (i = 1; i <= j; i++)
        {
            if (L.r[i + 1].key < L.r[i].key)
            {
                flag = 1;
                t = L.r[i];
                L.r[i] = L.r[i + 1];
                L.r[i + 1] = t;
            }
        }
        j--;
    }
}

//快速排序
int PartitionQ(SqList &L, int low, int high) //一趟快速排序,返回樞軸位置
{
    //1.選樞軸
    int pivotkey = L.r[low].key;
    L.r[0] = L.r[low];

    while (low < high)
    {
        while (low < high && pivotkey <= L.r[high].key)
            high--;
        L.r[low] = L.r[high];
        while (low < high && pivotkey >= L.r[low].key)
            low++;
        L.r[high] = L.r[low];
    }
    L.r[low] = L.r[0];

    return low;
}
void QSort(SqList &L, int low, int high)
{
    int pivotloc;

    if (low < high)
    {
        pivotloc = PartitionQ(L, low, high); //以樞軸爲支點將表分爲兩部分,返回數軸的位置
        QSort(L, low, pivotloc - 1);         //遞歸左子表
        QSort(L, pivotloc + 1, high);        //遞歸右子表
    }
}
void QuickSort(SqList &L)
{
    QSort(L, 1, L.length);
}

//簡單選擇排序
void SelectSort(SqList &L)
{
    int i, j, k;
    RedType t;

    for (i = 1; i < L.length; i++)
    {
        k = i;
        for (j = i + 1; j <= L.length; j++)
            if (L.r[j].key < L.r[k].key)
                k = j;
        if (k != i)
        {
            t = L.r[i];
            L.r[i] = L.r[k];
            L.r[k] = t;
        }
    }
}

//堆排序 調整堆
void HeapAdjust(SqList &L, int s, int m)
{
    RedType rc;
    int j;

    rc = L.r[s];
    for (j = 2 * s; j <= m; j *= 2)
    {
        while (j < m && L.r[j].key < L.r[j + 1].key)
            j++; //s與左右孩子較大的比較,這是堆排序的性質決定的
        if (rc.key >= L.r[j].key)
            break;
        L.r[s] = L.r[j];
        s = j;
    }
    L.r[s] = rc;
}

//建初堆
void CreateHeap(SqList &L)
{
    int n = L.length;
    int i;

    for (i = n / 2; i > 0; i--)
        HeapAdjust(L, i, n);
}

//堆排序
void HeapSort(SqList &L)
{
    int i;
    RedType x;
    CreateHeap(L);

    for (i = L.length; i > 0; i--)
    {
        x = L.r[1];
        L.r[1] = L.r[i];
        L.r[i] = x;

        HeapAdjust(L, 1, i - 1);
    }
}

//歸併排序
void Merge(SqList R, SqList &T, int low, int mid, int high)
{
    int i, j, k;
    i = low;
    j = mid + 1;
    k = low;
    while (i <= mid && j <= high)
    {
        if (R.r[i].key <= R.r[j].key)
            T.r[k++] = R.r[i++];
        else
            T.r[k++] = R.r[j++];
    }

    while (i <= mid)
        T.r[k++] = R.r[i++];
    while (j <= high)
        T.r[k++] = R.r[j++];
}
void Msort(SqList R, SqList &T, int low, int high)
{
    int mid;
    SqList S; //輔助存儲空間
    if (low == high)
        T.r[low] = R.r[low];
    else
    {
        mid = (low + high) / 2;
        Msort(R, S, low, mid);
        Msort(R, S, mid + 1, high);
        Merge(S, T, low, mid, high);
    }
}
void MergeSort(SqList &L)
{
    Msort(L, L, 1, L.length);
}

int main()
{
    SqList sq;
    int index;
    int dk[] = {5, 3, 1};

    while (1)
    {
        menu();
        printf("請輸入排序類型:\n");
        scanf("%d", &index);
        if (!index)
            return 0;
        //輸入
        InSqList(sq);
        //輸出
        OutPrintSqList(sq);
        switch (index)
        {
        case 1:
            InsertSort(sq); //直接插入排序
                            //輸出
            break;
        case 2:
            BInsertSort(sq); //折半插入排序
            break;
        case 3:
            ShellSort(sq, dk, 3);
            break;
        case 4:
            BubbleSort(sq);
            break;
        case 5:
            QuickSort(sq);
            break;
        case 6:
            SelectSort(sq);
            break;
        case 7:
            HeapSort(sq);
            break;
        case 8:
            MergeSort(sq);
            break;
        }
        printf("排序後:\n");
        //輸出
        OutPrintSqList(sq);

        printf("*************第4個49之前的位序是:%d**************\n", sq.r[4].otherinfp);
        system("pause");
    }

    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章