字典排序思路见下图

图片描述

//Lexicographic_Permute 字典排序算法
#include<iostream>
using namespace std;

//判断最后一个排列,是否存在 2个元素是升序的, 并记录最右升序左边那个数的位置
//比如:(1 5 2 6 3) 升序(<1,5>、<2 ,6>),记录 2所在位置 loc = 2
int judge_increase(int r[], int n);

//找出 > r[loc] 的最大值所在位置,从loc后面查找
//上例:3 > r[2] = 2, 故 最大索引值,  j = 4
int check_bigger_than_loc(int r[], int loc, int n);

//反序操作 将r 的first 到 end 之间的元素反向
void turn_permute(int r[], int first, int end); \

//准备好后,字典排序
void lexicographic_permute(int n);

int main()
{
    int n;
    while (cin >> n, n != EOF)
    {
        lexicographic_permute(n);
    }
    return 0;
}

int judge_increase(int r[], int n)
{
    int loc = -1;//-1表示不能往后面生成排列了
    for (int i = 0; i < n; i++)
    {
        if (r[i] < r[i + 1])
        {
            loc = i;
        }
    }
    return loc;
}
int check_bigger_than_loc(int r[], int loc, int n)
{
    int j = -1;
    int m = r[loc];//记录当前值
    for (int i = loc; i < n; i++)
    {
        if (m < r[i])
        {
            j = i;
        }
    }
    return j;
}
void turn_permute(int r[], int first, int end)
{
    //偶数个
    int m = (first + end) % 2;
    int mid = (first + end) / 2;
    int temp = 0;
    if (m == 0)
    {
        for (int i = first, j = end; i <= mid, j > mid; i++, j--)
        {
            temp = r[i];
            r[i] = r[j];
            r[j] = temp;
        }
    }
    //奇数个
    else
    {
        for (int i = first, j = end; i < mid, j > mid; i++, j--)
        {
            temp = r[i];
            r[i] = r[j];
            r[j] = temp;
        }
    }
}

void lexicographic_permute(int n)
{
    //初始化 为 1...n 的排列
    int r[100];
    int i;//记录 r[i] < r[i+1] 最远端的i位置
    int j;//j >= i+1, 记录r[j] > r[i] ,最远端的j位置
    int temp;
    for (int i = 0; i < n; i++)
    {
        r[i] = i + 1;
    }
    while ((i = judge_increase(r, n)) != -1)
    {
        j = check_bigger_than_loc(r, i, n);
        //交换 r[i] 和 r[j]
        temp = r[i];
        r[i] = r[j];
        r[j] = temp;
        //反序
        turn_permute(r, i + 1, n - 1);
        //输出
        for (int i = 0; i < n; i++)
        {
            cout << r[i] << " ";
        }
        cout << endl;
    }
}

结果展示

clipboard.png

c函数解释

  1. 函数简介
    介绍两个和字典排序相关函数

next_permutation prev_permutation
bool next_permutation(iterator start, iterator end)
查找下一个比当前排列的排列,若存在返回true
参数表示用一个数据的一部分生成排列
prev_permutation 查找下一个比当前排列的排列
一旦调用函数,若存在下一排列,则,数组排列顺序将会改变
比如:r[5]= {1,5,2,3,4}看代码演示
头文件 #include <algorithm>

执行过程
图片描述

#include <iostream>
#include <algorithm>
using namespace std;

void printf_r(int r[])
{
    for (int i = 0; i < 5; i++)
        cout << r[i];
    cout << endl;
}

int main()
{
    int r[5] = { 1,5,2,3,4 };
    cout << "原数组:\t    ";
    printf_r(r);

    next_permutation(r, r + 5);//注意是+5,不是+4;
    cout << "now数组:\t";
    printf_r(r);

    prev_permutation(r, r + 5);
    cout << "now数组:\t";
    printf_r(r);

    next_permutation(r + 1, r + 4);
    cout << "now数组:\t";
    printf_r(r);

    prev_permutation(r + 1, r + 4);
    cout << "now数组:\t";
    printf_r(r);
    return 0;
}

结果展示

clipboard.png


Light
11 声望0 粉丝