排序法总结

冒泡排序法

从低到高慢慢扩大已排序部分。找到未排序部分的第一个位置,然后从数组末尾开始依次比较相邻两个元素,如果大小关系相反则交换位置。这样可以保证每次都把最小的那个换到最前面。如果某一次没有元素交换,则表示排序完成。

例题:Bubble Sort

  • 输入n和数组,输出排序后的数组和交换次数。交换次数即逆序数
int exchange = 0;       //交换次数
bool flag = true;       //判断是否已经排好序
int index = 0;          //表示未排序部分的最小值
while (flag && index < n)
{
    flag = false;
    for (int j = n - 1; j >= index + 1; j--)
        if (a[j - 1] > a[j])
        {
            swap(a[j - 1], a[j]);
            exchange ++;
            flag = true;
        }
    index++;                   //每一次循环结束表示确定了一个min
}

插入排序法

如果只有1个数就是已经排好序的,所以从第2个开始确定这个数应该插入到已排好序的数组的哪个位置。1. 取出未排序部分的开头元素赋给v。2. 在已排序部分,将所有比v大的元素向后移动一个单位。3. 将已取出的元素v插入空位。

例题:Insertion Sort

for (int i = 1; i < n; i++)     //从第2个元素开始插入已排序部分
{
    int key = a[i];
    int j;
    for (j = i - 1; j >= 0 && key < a[j]; j--)  //不符合条件的情况j == -1或是key >= a[j]
        a[j + 1] = a[j];
    a[j + 1] = key;                    //注意这里是j + 1
    //Print(n);
}
  • 优化:在已排序数组中找到该数的插入位置可以采用二分算法

选择排序法

从坐标0开始,每次找出最小的那个元素去替换未排序的开始元素。

例题:Selection Sort

int exchange = 0;
for (int i = 0; i < n - 1; i++)
{
    int minj = i;
    for (int j = i; j < n; j++)
        if (a[j] < a[minj])
        minj = j;                   //找到值最小的元素
    swap(a[minj], a[i]);
    if (i != minj)
        exchange++;
}

归并排序法

以整个数组为对象执行 mergeSort m e r g e S o r t :
1.将给定的包含 n n 个元素的局部数据“分割”成两个局部数组,每个数组各包含n/2个元素。 (Divide) ( D i v i d e )
2.对两个局部数组分别实行 mergeSort m e r g e S o r t 排序。 (Solve) ( S o l v e )
3.通过 merge m e r g e 将两个已排序完毕的局部数组“整合”成一个数组。 (Conquer) ( C o n q u e r )

例题:Merge Sort

void merge(int left, int mid, int right)
{
    int x = mid - left;
    int y = right - mid;
    for (int i = 0; i < x; i++)
        L[i] = a[left + i];
    for (int i = 0; i < y; i++)
        R[i] = a[mid + i];

    L[x] = R[y] = MAX;
    int i = 0, j = 0;
    for (int k = left; k < right; k++)
    {
        if (L[i] <= R[j])
            a[k] = L[i++];
        else
            a[k]=R[j++]
    }
}

void MergeSort(int left, int right)
{
    if (left + 1 < right)
    {
        int mid = (left + right) >> 1;
        MergeSort(left, mid);
        MergeSort(mid, right);
        merge(left, mid, right);
    }
}

快速排序法

以整个数组为对象执行 quickSort q u i c k S o r t
1. 通过分割将对象局部数组分割为前后两个局部数组。 (Divide) ( D i v i d e )
2. 对前半部分的局部数组执行 quickSort q u i c k S o r t (Solve) ( S o l v e )
3. 对后半部分的局部数组执行 quickSort q u i c k S o r t (Solve) ( S o l v e )

例题:Quick Sort

int partition(int left, int right)
{
    Card x = a[right];
    int i = left - 1;
    for (int j = left; j < right; j++)
    {
        if (a[j].val <= x.val)
        {
            i++;
            swap (a[i], a[j]);
        }
    }
    swap(a[i+1], a[right]);
    return i + 1;
}

void quickSort(int left, int right)
{
    int selected;
    if (left < right)
    {
        selected = partition(left, right);
        quickSort(left, selected - 1);
        quickSort(selected + 1, right);
    }
}

如何证明快速排序是稳定的还是不稳定的?

  • id i d 标记,和 mergeSort m e r g e S o r t 的结果相对比。
排序方法平均时间最坏情况最好情况辅助空间稳定性
插入排序 O(n2) O ( n 2 ) O(n2) O ( n 2 ) O(n) O ( n ) O(1) O ( 1 ) false f a l s e
选择排序 O(n2) O ( n 2 ) O(n2) O ( n 2 ) O(n2) O ( n 2 ) O(1) O ( 1 ) true t r u e
冒泡排序 O(n2) O ( n 2 ) O(n2) O ( n 2 ) O(n) O ( n ) O(1) O ( 1 ) true t r u e
归并排序 O(nlogn) O ( n l o g n ) O(nlogn) O ( n l o g n ) O(nlogn) O ( n l o g n ) O(n) O ( n ) true t r u e
快速排序 O(nlogn) O ( n l o g n ) O(n2) O ( n 2 ) O(nlogn) O ( n l o g n ) O(logn) O ( l o g n ) false f a l s e
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值