几种排序算法的实现与比较(c++容器)

本文详细介绍了在C++中实现插入排序、归并排序和快速排序的方法,包括代码实现和测试截图。三种排序算法分别在数据结构上使用了容器,通过迭代器进行遍历,并提供了不同方式的实现,如插入排序的迭代器传递和容器传递,快速排序的扫描方向选择等。同时,讨论了每种排序算法的时间复杂度和结束条件。

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

1、插入排序


Description:使用插入排序将容器内数进行排序
Idea:
1.从容器中取数,每次都把取到的数插入到正确到位置。

Q&A:

1.Q:当拿到一个数a时,如何将这个数插入到正确的位置?

   A:将a与已经插入到所有数进行比较,找到第一个比a大到数位置,在这个数到前面插入之;
2.Q:如何判断已经排完序,即结束条件是什么?
   A:当所有到数都插入时,即取数数组到元素为空,即结束,可以设置一个计数器count;
Input:未排序的数组
Output:字典排序的数组
Data Structure:使用容器存放数组,利用迭代器进行遍历,函数传递迭代器,返回排好序容器到迭代器;
Complexity:O(n^2)


实现代码(分传递迭代器与传递容器两种):

//传递迭代器
void insert_sort(iter first, iter last)
{
    int flag = 0;
    int tem = 0;
    iter it;
    for(iter i = first+1;i != last;i++)
    {
        flag = 0;
        tem  = *i;
        for(iter j = first;j != i;j++)
        {
            if(*i > *j)flag++;
            else 
            {
                it = first+flag;
                copy_backward(it,i,i+1);
                *(it) = tem;
            }
        }
    }
}

//传递容器
vec insert_sort(vec &array)
{
    int flag = 0;
    iter first = array.begin();
    iter it;
    int tem = 0;
    for(iter i = array.begin() + 1; i != array.end(); i++)
    {
        flag = 0;
        tem = *i;
        for(iter j = array.begin(); j !=i; j++)
        {
            if(*i > *j)
                flag++;
            else  
            {
                it = first+flag;
                copy_backward(it,i,i+1);
                *(it) = tem;
            }
        }
    }
    return array;
}


测试截图:



2、归并排序


Description: 利用归并递归到思想,进行数组到字典排序;
Idea:
1.将问题逐步细化,进行递归求解.
Q&A:
1.Q:递归终止条件是什么?
   A:当要分割的数的数目为1时;
2.Q:merge函数如何实现?
   A:函数原型:merge(iter val_it,iter res_it,int start,int first_end,int end);其中参数val为待归并到
    容器的迭代器,rel为归并后保存数据容器的迭代器,start为第一个归并集合与val间的距离,相当于
    (val+start)为归并数据的起始位置,同理(val+first_end)为第一个集合到最后一个元素,
    (val+first_end+1)为第二个集合的起始位置,(val+end)为第二个集合最后一个元素。
Input:未排序的数组
Output:字典排序的数组
Data Structure:
1.使用容器存放数组,利用迭代器进行遍历,函数传递迭代器,返回排好序容器的迭代器;
2.原始排序数组存放在value容器中,归并时到数据保存在result容器中。
Complexity:(nlogn)

实现代码:

void merge_sort(vec &v,int start,int end)
{
    if(start < end)
    {
        int mid = (start + end)/2;
        merge_sort(v,start,mid);
        merge_sort(v,mid+1,end);
        merge(v,start,mid,end);
    }
}

//按序归并两个容器
void merge(vec &v,int start,int first_end,int end)
{
    int n = first_end - start +1;
    int m = end - first_end;
    int first_count = 0,second_count = 0;
    vec v_first(n + 1);
    vec v_second(m + 1);

    copy(v.begin() + start,v.begin() + first_end + 1,v_first.begin());
    copy(v.begin() + first_end + 1,v.begin() + end + 1,v_second.begin());
    *(v_first.end()-1) = 2147483647; 
    *(v_second.end()-1) = 2147483647;

    int value_first = 0,value_second = 0;
    for(int i = 0,j = 0,k = start;k != end + 1;++k)
    {
        value_first = *(v_first.begin() + i);
        value_second = *(v_second.begin() + j);
        if(value_first < value_second)
        {
            *(v.begin() + k) = value_first;
            i++;
        }
        else if(value_first >=value_second)
        {
            *(v.begin() + k) = value_second;
            j++;
        }
    }
}

测试截图:





3、快速排序:


Description:利用快排分治的思想将n个数排序。
Idea:
1.给定一个数组,选定一个基轴,假定每次选定第一个数为基轴,则从最后一个数进行扫描,找到第一
  个小于基轴的数,并放入基轴位置,此时得到一个空位置,然后从基轴下一个位置扫描,找到第一个
  大于基轴的数。之后每次都以此方向扫描,并从上次扫描的下一位置扫描。此函数记为partition().
2.基准位置确定后,在分别在其两端再次调用partition()函数。
Q&A:
1.Q:partition函数什么时候结束?
   A:从左和从右扫描的计数器相等时结束。
Input:未排序的数组
Output:字典排序的数组
Data Structure:使用容器存放数组,利用迭代器进行遍历,函数传递迭代器,返回排好序容器到迭代器;
Complexity:O(nlogn)-O(n^2)


实现代码(扫描分从左往右和从两端向中间两种):

void quick_sorts(iter it,int start,int end)
{
    int p = 0;
    if(start < end)
    {
        p = partitions(it,start,end);
        quick_sorts(it,start,p - 1);
        quick_sorts(it,p + 1,end);
    }
}


void quick_sort(iter it,int start,int end)
{
    int p = 0;
    if(start < end)
    {
        p = partition(it,start,end);
        quick_sort(it,start,p - 1);
        quick_sort(it,p + 1,end);
    }
}

//From left to right to scan
int partitions(iter it,int start,int end)
{
    int x = *(it+end),i = start - 1;
    for(int j = start;j < end;++j)
    {
        if(*(it + j) <= x)
        {
            ++i;
            swap_ranges(it + i,it + i + 1,it + j);
        }
    }
    swap_ranges(it + i + 1,it + i + 2,it + end);
    return i+1;
}


//From left and right to middle to scan
int partition(iter it,int start,int end)
{
    int left,right;
    int tem = 0;
    int base = *(it + start);
    int l_pos = 0,r_pos = 0,pos = 0;
    pos = start;
    for(left = start + 1,right = end,l_pos = start;left <= right;)
    {
        while(left <= right)
        {
            if(*(it + right) <= base)
            {
                *(it + l_pos) = *(it + right);
                r_pos = right;
                pos = r_pos;
                --right;
                break;
            }
            else --right;
        }
        while(left <= right)
        {
            if(*(it + left) >=base)
            {
                *(it + r_pos) = *(it + left);
                l_pos = left;
                pos = l_pos;
                ++left;
                break;
            }
            else ++left;
        }
    }
    *(it + pos) = base;
    return pos;
}


测试截图:



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值