算法-排序-交换排序(冒泡和快速排序)

本文介绍了交换排序的两种常见算法——冒泡排序和快速排序。冒泡排序通过重复遍历序列并交换相邻元素来排序,是稳定的排序算法,但效率较低。快速排序则采用分治策略,选取分界点将序列分为两部分,递归处理,但它是非稳定的排序算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

交换排序

这次学习了两种交换排序算法:冒泡排序和快速排序算法;两种方法都是基于元素交换的概念而来的,交换排序的基本思想是:两两比较待排序记录的关键字,发现两个记录的次序相反时即进行交换,直到没有反序的记录为止。下面简单介绍其基本原理。

1、冒泡排序
基本原理:把序列的每个元素当成一个气泡,则轻的气泡在上,重的在下。排序过程为每次从最下面的气泡R[n]开始,让它与上一个气泡R[n-1]比较大小
若比上面的小,则交换顺序,否则不改变。然后进行下一步,对R[n-1]和R[n-2]进行相同的比较,直到R[1]和R[0],这样一趟比较就将序列中最小的额
元素放在了序列的最上面,然后进行第二趟比较,从R[n]到R[1],将第二小的元素放在R[1]位置,依次类推,最后就可以得到排列的序列
演示动画:http://student.zjzk.cn/course_ware/data_structure/web/flashhtml/maopaopaixu.htm

算法为就地排序,是稳定的,由于元素移动次序多,因此性能比直接插入排序要差

2、快速排序
基本原理:采用分治的思想,将问题分成若干个结构相同的问题通过递归来解决。假设一个序列R,i,j作为上下边界,在R中取一个值作为分界点,把R中的值分成两边,左边的比R小,右边的比R大,这样再分别对左右两边的值做相同的运算,最终就可以得到排列好的序列。
演示动画:http://student.zjzk.cn/course_ware/data_structure/web/flashhtml/kuaisupaixu.htm

排序是非稳定的

下面来看具体实现:

#include <iostream>
#include <vector>
using namespace std;
const int N = 20;    //定义常量    也可以这样 #define N 20 

void disp(vector<int> vec);   //输出函数,
void bubble(vector<int> &vec,int n);   //冒泡算法
void quicksock(vector<int> &vec, int l, int r);      //快速排序
int partition(vector<int> &vec,int l, int r);       //快速算法---->划分函数

int main()
{
    vector<int> vec1(N),vec2;
    int a[N] = {2 ,19 ,3 ,25 ,4 ,0,8,22,10,2,9,45,12,16,21,41,6,18,34,10};
    for(int i = 0; i < N; i++)
    {
        vec1[i] = a[i];
    }
    vec2 = vec1;
    disp(vec1);      //排序前序列1
    disp(vec2);      //排序前序列2
    bubble(vec1,N);   //冒泡排序
    quicksock(vec2,0,N-1);      //快速排序
    disp(vec1);      //排序后序列1
    disp(vec2);      //排序后序列2
    return 0;
}


void disp(vector<int> vec)   //输出函数
{
    cout << "排列顺序为:";
    for(int i = 0; i < N; i++)
    {
        cout << vec[i] << "    ";
    }
    cout << endl;
}

void bubble(vector<int> &vec,int n)
{
    int flag,temp;
    for(int i = 0; i < n; i++)
    {
        flag = 0;                   
        //作为标记,看这一趟有没有进行交换,若没有则不再需要交换,直接退出循环
        for(int j = n-1; j >=i+1; j--)    //注意j的范围
        {
            if(vec[j] < vec[j-1])
            {
                temp = vec[j];
                vec[j] = vec[j-1];
                vec[j-1] = temp;
                flag = 1;
            }
        }
        if(!flag)  //这一趟没进行交换
            return ;      //直接跳出方法
    }
}



void quicksock(vector<int> &vec, int l, int r)
{
    int pivotpos;     //划分后基准(分届点)位置
    if(l<r)
    {
        pivotpos = partition(vec,l,r);         //划分
        quicksock(vec,l,pivotpos-1);       //对基准左边的序列递归排序
        quicksock(vec,pivotpos+1,r);       //对基准右边的序列递归排序
    }
}

int partition(vector<int> &vec,int l, int r)
{
    int temp;
    int pivot = vec[l];  //第一个数作为基准,需与每次运算区间相关,不能是总的序列的一个固定值,只能固定位于区间相对位置
    while(l<r)
    {
        while (l<r && vec[r] >= pivot)       //过滤掉大于基准的值
            r--;
        if(l<r && vec[r] < pivot)        //找到第一个小于基准的值,并交换
        {
            temp = vec[l];                  //若是基准为序列第一个数的话不用交换,直接赋值就行,因为第一个值保存在pivot中不会丢失
            vec[l] = vec[r];
            vec[r] = temp;
            l++;
        }
        while(l<r && vec[l] <= pivot)       //过滤掉小于基准的值
            l++;
        if(l<r && vec[l] > pivot)   //找到大于基准的值,交换放到基准右边
        {
            temp = vec[r];
            vec[r] = vec[l];
            vec[l] = temp;
            r--;
        }
    }
    vec[l] = pivot;    //由于上面用的是交换,这里也可以省略,若是用赋值方式则需要将这个值传递过去
    return l;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值