全排列(二)字典序方式与next_permutation的联系
来源:互联网 发布:路由器限速软件 编辑:程序博客网 时间:2024/06/06 03:31
1、字典序原理
对给定的字符集中的字符规定了一个先后关系,在此基础上规定两个全排列的先后是从左到右逐个比较对应的字符的先后。
(1)生成给定全排列的下一个排列 所谓一个的下一个就是这一个与下一个之间没有其他的。这就要求这一个与下一个有尽可能长的共同前缀,也即变化限制在尽可能短的后缀上。
(2)序数公式
有从 1 到 n 的连续的 n 个自然数,其全排列按照从小到大排列,次序从 0 到 n!-1 ,总共 n! 个。现有其全排列中的一组 “ 、 、 …… ”,其全排列次序为:
(3)具体步骤
所谓字典序法就是按照字典排序的思想逐一产生所有排列。比如1,2,3,4四个数字进行全排列,先1234,1243,1324,1342,1423,1432,…4321。
由1243生成1324的过程:
1). 1243从右向左找第一个正序对24
2). 从右向左找第一个大于2的数,3
3). 交换2与3的位置的:1342
4). 把3后面的数字全部反序的:1324
总结:
1). 从右向左找到第一个正序Pi < Pi+1 (i+1为下标,也即只比较相邻位置)
2). 从右向左找到第一个大于Pi的数Pj
3). 交换Pi与Pj
4). 将Pj后面的数全部反序,得到一个排序
这4个步骤保证相邻两个序列的序数(通过序公式计算得)相差为1,准确说是每次增加1,从这个角度来看,每个序列也可以对应一个数值
2、next_permutation方式与字典序方式之间的联系
STL中algorithm算法里面的next_permutation方法便是通过字典序方式实现的,见下面STL源码:
bool next_permutation(_BidirectionalIter __first, _BidirectionalIter __last) { __STL_REQUIRES(_BidirectionalIter, _BidirectionalIterator); __STL_REQUIRES(typename iterator_traits<_BidirectionalIter>::value_type, _LessThanComparable); if (__first == __last) return false; _BidirectionalIter __i = __first; ++__i; if (__i == __last) return false; __i = __last; --__i; for(;;) { _BidirectionalIter __ii = __i; --__i; if (*__i < *__ii) { //从右向左找到第一个正序 Pi < Pi+1 _BidirectionalIter __j = __last; {} while (!(*__i < *--__j)) //从右向左找到第一个大于Pi的数Pj iter_swap(__i, __j); //交换Pi和Pj reverse(__ii, __last); //将原Pi位置后面的序列全部反序 return true; } if (__i == __first) { reverse(__first, __last); return false; } }}
自己通过字典序方式实现的next_permutation:
#include<iostream>using namespace std;void swap(int &a,int &b){ int temp; temp=a; a=b; b=temp;}void reverse(int *num,int start,int end){ int i=start; int j=end; while(i<j) { swap(num[i],num[j]); i++; j--; }}bool next_permutation(int *num,int len){ if(len<2) { return false; } int i,j; i=j=len-1; i--; for(;i>-1;) { if(num[i]<num[j]) { int k; for(k=len-1;k>i;k--) { if(num[k]>num[i]) {break;} } swap(num[i],num[k]); reverse(num,j,len-1); return true; }else { i--; j--; } }}int main(){ int num[3]={1,2,3}; cout<<"初始序列: "<<num[0]<<" "<<num[1]<<" "<<num[2]<<endl; do { cout<<num[0]<<" "<<num[1]<<" "<<num[2]<<endl; }while(next_permutation(num,3)); return 0;}
阅读全文
0 0
- 全排列(二)字典序方式与next_permutation的联系
- STL之 next_permutation函数{(全排列)按字典序!!!!!}
- 全排列(一)next_permutation方式实现
- 全排列与next_permutation
- POJ 1833 排列(字典序全排列、next_permutation()、copy+流迭代器)
- next_permutation 与 prev_permutation的用法 (全排列)
- 全排列(next_permutation)
- next_permutation(全排列)
- next_permutation函数 字典序排列
- 全排列与字典序排列
- 全排列next_permutation()的用法
- 【原创】黑科技库(二): 全排列函数 next_permutation
- (转载)全排列next_permutation
- 全排列函数 next_permutation()
- next_permutation函数(全排列)
- next_permutation函数(全排列)
- 全排列(next_permutation,递归)
- 字典序与next_permutation
- (8)hadoop学习——内部表和外部表
- Bitmap转换为Drawable时,图片大小问题
- 谈谈RDD、DataFrame、Dataset的区别和各自的优势
- mariadb
- 蓝桥杯 算法训练 表达式计算
- 全排列(二)字典序方式与next_permutation的联系
- BRIEF特征点描述算法
- Redis安装及主从配置
- gz和bz2包解压命令
- Well内嵌效果
- 有一种人
- 基于模型的PLC程序设计一 状态机介绍
- 有关set的一点应用
- JAVA编程思想读书笔记(1--7章)