c/c++常用算法(9) -- 基本排序算法(交换排序)

交换排序概念


      交换排序的基本思想是:两两比较待排序记录的关键字,发现两个记录的次序相反时即进行交换,直到没有反序的记录为止。

应用交换排序基本思想的主要排序方法有:冒泡排序和快速排序


1.冒泡


1.1  排序思想


        依次比较相邻的两个记录的关键字,若两个记录是反序的(即前一个记录的关键字大于后前一个记录的关键字),则进行交换,直到没有反序的记录为止。

①首先将L->R[1]与L->R[2]的关键字进行比较,若为反序(L->R[1]的关键字大于L->R[2]的关键字),则交换两个记录;然后比较L->R[2]与L->R[3]的关键字,依此类推,直到L->R[n-1]与L->R[n]的关键字比较后为止,称为一趟冒泡排序,L->R[n]为关键字最大的记录。

②  然后进行第二趟冒泡排序,对前n-1个记录进行同样的操作。

   一般地,第i趟冒泡排序是对L->R[1 … n-i+1]中的记录进行的,因此,若待排序的记录有n个,则要经过n-1趟冒泡排序才能使所有的记录有序。


1.2  排序示例


       设有9个待排序的记录,关键字分别为23, 38, 22, 45, 23,67, 31, 15, 41,冒泡排序的过程如图10-6所示。




1.3  算法实现


main.cpp

#include <iostream>
#include <time.h>

#define SIZE 10

void BubbleSort(int *a,int len)
{
    int i,j,k,temp;
    
    for (i=0; i<len-1; i++)
    {
        for (j = len-1; j>i; j--)
        {
            if (a[j-1]>a[j])
            {
                temp = a[j-1];
                a[j-1] = a[j];
                a[j] = temp;
            }
        }
        printf("第%d步排序结果:",i);
        for (k=1; k<len; k++)
        {
            printf(" %d",a[k]);
        }
        printf("\n");
    }
}

int main(int argc, const char * argv[])
{
    int shuzu[SIZE],i;
    
    srand(time(NULL));
    for (i=0; i<SIZE; i++)
    {
        shuzu[i] = rand() % 100;
    }
    
    printf("排序前的数组为:\n");
    
    for (i=0; i<SIZE; i++)
    {
        printf(" %d",shuzu[i]);
    }
    printf("\n");
    
    BubbleSort(shuzu, SIZE);
    
    printf("排序后的数组为:\n");
    for (i=0; i<SIZE; i++)
    {
        printf(" %d",shuzu[i]);
    }
     printf("\n");
    // std::cout << "Hello, World!\n";
    return 0;
}

运行效果(随机生成数据):

      


2.快速排序


2.1  快速排序思想


      通过一趟排序,将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,再分别对这两部分记录进行下一趟排序,以达到整个序列有序。


2.2  快速排序过程


       设待排序的记录序列是R[s…t] ,在记录序列中任取一个记录(一般取R[s])作为参照(又称为基准枢轴),以R[s].key为基准重新排列其余的所有记录,方法是:

所有关键字比基准小的放R[s]之前;

所有关键字比基准大的放R[s]之后。

       以R[s].key最后所

位置i作为分界,将序列R[st]分割成两个子序列,称为一趟快速排序

2.3  一趟快速排序方法


        从序列的两端交替扫描各个记录,将关键字小于基准关键字的记录依次放置到序列的前边;而将关键字大于基准关键字的记录从序列的最后端起,依次放置到序列的后边,直到扫描完所有的记录。

        设置指针low,high,初值为第1个和最后一个记录的位置。

设两个变量i,j,初始时令i=low,j=high,以R[low].key作为基准(将R[low]保存在R[0]中)。

        ①从j所指位置向前搜索:将R[0].key与R[j].key进行比较:

                ◆ 若R[0].key≤R[j].key:令j=j-1,然后继续进行比较,直到i=j或R[0].key>R[j].key为止;

                ◆若R[0].key>R[j].key:R[j]ÞR[i],腾空R[j]的位置,且令i=i+1;

        ②从i所指位置起向后搜索:将R[0].key与R[i].key进行比较:

                ◆若R[0].key≥R[i].key:令i=i+1,然后继续进行比较,直到i=j或R[0].key<R[i].key为止;

                ◆若R[0].key<R[i].key:R[i]ÞR[j],腾空R[i]的位置,且令j=j-1;

        ③重复①、②,直至i=j为止,i就是R[0] ( 基准 )所应放置的位置。

2.4  一趟排序示例


       设有6个待排序的记录,关键字分别为29, 38, 22, 45, 23 ,67,一趟快速排序的过程如图10-7所示。




2.4  代码:


main.cpp

#include <iostream>
#include <time.h>

#define SIZE 10


void QuickSort(int *arr,int left, int right)
{
    int f,t;
    int rtemp,ltemp;
    
    ltemp = left;
    rtemp = right;
    f = arr[(left + right)/2];  //中间位置的值为分界值
    while (ltemp < rtemp)
    {
        while (arr[ltemp] < f)
        {
            ++ltemp;
        }
        while (arr[rtemp] > f)
        {
            --rtemp;
        }
        if (ltemp <= rtemp)
        {
            t = arr[ltemp];
            arr[ltemp] = arr[rtemp];
            arr[rtemp] = t;
            --rtemp;
            ++ltemp;
        }
    }
    if (ltemp == rtemp)
    {
        ltemp++;
    }
    
    if (left < rtemp)
    {
        QuickSort(arr, left, ltemp-1);
    }
    
    if (ltemp < right)
    {
        QuickSort(arr, rtemp +1,right );
    }
}



int main(int argc, const char * argv[])
{
    int shuzu[SIZE],i;
    
    srand(time(NULL));
    for (i=0; i<SIZE; i++)
    {
        shuzu[i] = rand() % 100;
    }

    printf("排序前的数组为:\n");
    
    for (i=0; i<SIZE; i++)
    {
        printf(" %d",shuzu[i]);
    }
    printf("\n");

    QuickSort(shuzu,0,SIZE-1);

    printf("排序后的数组为:\n");
    for (i=0; i<SIZE; i++)
    {
        printf(" %d",shuzu[i]);
    }
     printf("\n");
    // std::cout << "Hello, World!\n";
    return 0;
}

运行效果(随机生成数据):


        


参考书籍:《C/C++常用算法手册》  《数据结构-清华大学严蔚敏》


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

热血枫叶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值