数据结构基础(3) --Permutation & 插入排序

简介: Permutation(排列组合)排列问题: 设R = {r1, r2, ... , rn}是要进行排列的n个元素, Ri = R-{ri}; 集合X中元素的全排列记为Permutatio...

Permutation(排列组合)

排列问题:

设R = {r1, r2, ... , rn}是要进行排列的n个元素, Ri = R-{ri}; 集合X中元素的全排列记为Permutation(X), (ri)Permutation(X)表示在全排列Permutation(X)的每一个排列前加上前缀ri得到的排列.

R的全排列可归纳定义如下:

当n=1时,Permutation(R)={r},r是集合R中唯一的元素;

当n>1时,Permutation(R)由(r1)Permutation(R1),(r2)Permutation(R2), ..., (rn)Permutation(Rn)构成。

依次递归定义,则可设计产生Permutation(X)的递归算法如下:

template <typename Type>
void permutation(Type *array, int front, int last)
{
    //已经递归到了最后一个元素
    if (front == last)
    {
        //打印输出
        for (int i = 0; i < front; ++i)
        {
            cout << array[i] << ' ';
        }
        cout << array[front] << endl;
        return ;
    }
    else
    {
        for (int i = front; i <= last; ++i)
        {
            // 不断的从下标为[front ~ last]的元素中选择一个元素
            //作为当前序列的开头元素
            std::swap(array[front], array[i]);
            permutation(array, front+1, last);
            std::swap(array[front], array[i]);
        }
    }
}

算法说明:

算法Permutation(array, k, m)递归地产生所有前缀是array[0:k-1],且后缀是array[k:m]的全排列的所有排列.函数调用(list, 0, n-1)则产生list[0:n-1]的全排列.

 

算法演示:

char str[] = “abc”;的递归调用过程如图:


小结:

虽然我们自己实现了Permutation, 但C++ STL中也实现了std::next_permutation算法, 在一般应用中, 我比较推荐使用STL中已经实现好的next_permutation, 毕竟STL的代码质量还是非常高的, 而且速度一点也不逊色于我们的实现;

 

插入排序

插入排序是低级排序中速度最快的一种(冒泡/选择/插入排序效率均为O(N^2)),但是跟快速排序(NlogN),归并排序(NlogN)还是有一定的差距的⊙﹏⊙b汗!

算法思想:

不断的从尚未排序的序列中选择一个元素插入到已经排好序的序列中(当然,会有一个选择插入位置的过程:选择一个位置, 该位置前的元素都比该元素小, 该位置后的元素都比该元素大),类似于现实生活中的斗地主的摸排过程.


//实现与解析
/**说明:
    outer:第一个未排序的元素
    inner:搜索第一个小于tmp的元素的位置
    tmp:  用于暂存第一个尚未排序的元素
*/
template <typename Type>
void insertionSort(Type *begin, Type *end) throw (std::range_error)
{
    if ((begin == end) || (begin == NULL) || (end == NULL))
        throw std::range_error("pointer unavailable");

    //假设第一个元素已经排好序了
    for (Type *outer = begin+1; outer < end; ++outer)
    {
        Type tmp = *outer;   //暂存第一个未排序的元素
        Type *inner = outer;

        //inner 不断寻找一个位置(*(inner-1) <= tmp),
        //使得tmp->*inner(tmp所保存的值插入到inner位置)
        while (inner > begin && *(inner-1) > tmp)
        {
            *inner = *(inner-1);    //元素后移
            -- inner;               //指针前移
        }
        *inner = tmp;               //将元素插入已排序序列
    }
}

template <typename Iter>
void insertionSort(Iter begin, Iter end)
{
    return insertionSort(&(*begin), &(*end));
}
/**insertionSort_2算法的由来:
    可以使用*begin(序列的第一个元素)作为哨兵,
    这样就可以省去insertionSort 中第15行的inner > begin判断,
    但付出的代价是begin所指向的位置不能再存储有用的数据,
    只能被用作排序的哨兵 -> 以空间换时间(个人感觉没什么必要...)
*/
template <typename Type>
void insertionSort_2(Type *begin, Type *end) throw (std::range_error)
{
    if ((begin == end) || (begin == NULL) || (end == NULL))
        throw std::range_error("pointer unavailable");

    for (Type *outer = begin+2; outer < end; ++outer)
    {
        *begin = *outer;
        Type *inner = outer;

        //因为*begin不可能 > *begin, 所以该循环一定会退出
        while (*(inner-1) > *begin)
        {
            *(inner) = *(inner-1);
            --inner;
        }
        *inner = *begin;
    }
}

附-permutation与std::next_permutation测试代码

int main()
{
    vector<char> str;
    for (char ch = 'a'; ch <= 'c'; ++ch)
        str.push_back(ch);

    permutation(&(*str.begin()), 0, 2);

    cout << "----------" << endl;
    typedef vector<char>::iterator Iter_type;
    do
    {
        for (Iter_type iter = str.begin(); iter != str.end(); ++iter)
            cout << *iter << ' ';
        cout << endl;
    }
    while (std::next_permutation(str.begin(), str.end()));

    return 0;
}

目录
相关文章
|
2月前
|
算法 搜索推荐
数据结构与算法学习十一:冒泡排序、选择排序、插入排序
本文介绍了冒泡排序、选择排序和插入排序三种基础排序算法的原理、实现代码和测试结果。
24 0
数据结构与算法学习十一:冒泡排序、选择排序、插入排序
|
5月前
|
搜索推荐 测试技术
【数据结构常见七大排序(一)】—插入排序篇【直接插入排序】And【希尔排序】
【数据结构常见七大排序(一)】—插入排序篇【直接插入排序】And【希尔排序】
|
6月前
|
机器学习/深度学习 算法 搜索推荐
数据结构算法--2 冒泡排序,选择排序,插入排序
**基础排序算法包括冒泡排序、选择排序和插入排序。冒泡排序通过相邻元素比较交换,逐步将最大值“冒”到末尾,平均时间复杂度为O(n^2)。选择排序每次找到剩余部分的最小值与未排序部分的第一个元素交换,同样具有O(n^2)的时间复杂度。插入排序则类似玩牌,将新元素插入到已排序部分的正确位置,也是O(n^2)复杂度。这些算法适用于小规模或部分有序的数据。**
|
6月前
|
算法 搜索推荐
数据结构与算法-插入排序
数据结构与算法-插入排序
33 2
|
7月前
|
存储 搜索推荐 算法
[数据结构]————排序总结——插入排序(直接排序和希尔排序)—选择排序(选择排序和堆排序)-交换排序(冒泡排序和快速排序)—归并排序(归并排序)
[数据结构]————排序总结——插入排序(直接排序和希尔排序)—选择排序(选择排序和堆排序)-交换排序(冒泡排序和快速排序)—归并排序(归并排序)
|
7月前
|
C语言
【C语言/数据结构】排序(直接插入排序|希尔排序)
【C语言/数据结构】排序(直接插入排序|希尔排序)
53 4
|
7月前
|
搜索推荐 算法 C++
[数据结构]-玩转八大排序(一)&&插入排序&&选择排序
[数据结构]-玩转八大排序(一)&&插入排序&&选择排序
|
6月前
|
人工智能 算法 C语言
数据结构与算法——简单排序-冒泡排序、插入排序,时间复杂度下界(图示、代码、时间复杂度、定理)
数据结构与算法——简单排序-冒泡排序、插入排序,时间复杂度下界(图示、代码、时间复杂度、定理)
44 0
|
6月前
|
存储 搜索推荐
深入了解数据结构第四弹——排序(1)——插入排序和希尔排序
深入了解数据结构第四弹——排序(1)——插入排序和希尔排序
31 0
|
7月前
|
存储 算法 搜索推荐
【数据结构与算法】:插入排序与希尔排序
欢迎大家来到初阶数据结构的最后一小节:排序
【数据结构与算法】:插入排序与希尔排序