全排序算法

以前看过一些全排序算法,大致思路如下:

 

在数组中,轮流选一个元素作为头字符,然后剩下的数组元素在做全排序。这是一个典型的递归算法。

 

还有一个方法就是使用next_permutation这个标准库函数,这个函数的作用是一个范围的值变成字典序中的下一个值,即按字典序排的话,新的字符串(或数组)刚好是以前那个的下一位,原函数如下:

 

  template inline
   bool next_permutation(_BidIt _First, _BidIt _Last)
   { // permute and test for pure ascending, using operator<
   _BidIt _Next = _Last;
   if (_First == _Last || _First == --_Next)
   return (false);
  
   for (; ; )
   { // find rightmost element smaller than successor
   _BidIt _Next1 = _Next;
   if (*--_Next < *_Next1)
   { // swap with rightmost element that's smaller, flip suffix
   _BidIt _Mid = _Last;
   for (; !(*_Next < *--_Mid); )
   ;
   std::iter_swap(_Next, _Mid);
   std::reverse(_Next1, _Last);
   return (true);
   }
  
   if (_Next == _First)
   { // pure descending, flip all
   std::reverse(_First, _Last);
   return (false);
   }
   }
   }

 

分析next_permutation函数执行过程:

假设数列 d1,d2,d3,d4……

范围由[first,last)标记,调用next_permutation使数列逐次增大,这个递增过程按照字典序。例如,在字母表中,abcd的下一单词排列为abdc,但是,有一关键点,如何确定这个下一排列为字典序中的next,而不是next->next->next……

若当前调用排列到达最大字典序,比如dcba,就返回false,同时重新设置该排列为最小字典序。

返回为true表示生成下一排列成功。下面着重分析此过程:

根据标记从后往前比较相邻两数据,若前者小于(默认为小于)后者,标志前者为X1(位置PX)表示将被替换,再次重后往前搜索第一个不小于X1的数据,标记为X2。交换X1,X2,然后把[PX+1,last)标记范围置逆。完成。

要点:为什么这样就可以保证得到的为最小递增。

从位置first开始原数列与新数列不同的数据位置是PX,并且新数据为X2。[PX+1,last)总是递减的,[first,PX)没有改变,因为X2>X1,所以不管X2后面怎样排列都比原数列大,反转[PX+1,last)使此子数列(递增)为最小。从而保证的新数列为原数列的字典序排列next。

 

本段来自优快云博客,转载请标明出处:http://blog.youkuaiyun.com/aipb2008/archive/2008/03/29/2227490.aspx.

 

然后我仿着这个写了个类似的函数,仅仅用于对整形数组进行字典序排序

 

 

 

#include<iostream>
#include<algorithm>

using namespace std;
bool next_per(int a[],int n);

int main()
{
 int a[4] = {2,3,1,4};

 sort(a,a+4);

 do{
  for(int i = 0; i < 4; i++)
  {
   cout<<a[i]<<" ";
  }
  cout<<endl;
 }while(next_per(a,4));

 system("pause");

 return 0;
}

void swap_int(int a[], int x, int y)
{
 int temp = a[x];
 a[x] = a[y];
 a[y] = temp;
}

void reverse(int a[], int start , int end)
{
 if(start < end)
 {
  swap_int(a,start,end);
 }
}

bool next_per(int a[],int n)
{
 if(n == 1 || n == 0)
  return false;


 int m = n - 1;
 int next = a[n-1];
 for(;;)
 {
  int next1 =  a[m];
  if(a[--m] < next1)
  {
   int m1 = m;
   int end = n;

   for(;!(a[m1] < a[--end]););

   swap_int(a,m1,end);
   reverse(a,m + 1,n-1);
   return true;
   
  }

  if(m <= 0)
  {
   return false;
  }
 }
}

 

这是整个文件了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值