穷尽所有排列--下一个排列

#include <stdio.h>
#include
<string.h>
#include
<stdlib.h>
#include
<limits.h>

void swap(unsigned char *a, unsigned char *b);
/*
@brief reverse an array, whose index is equal and larger than lo, and
equal and smaller then high
*/
void reverse(unsigned char array[], int lo, int high);

/*
@brief to find next arrange in ascending order, and store it in array
*/
int larger_next(unsigned char array[], int lo, int high);

/*
@brief to find next arrange in descending order, and store it in array
@return 1: found successful 0: no number smaller exists
*/
int smaller_next(unsigned char array[], int lo, int high);

/*
@brief print an array, whose index is equal and larger than lo, and
equal and smaller then high
*/
void print(unsigned char array[], int lo, int high);

/*
@brief sort an array
@param order: 1 ascending 0 descending
*/
void sort(unsigned char array[], int lo, int high, int order);

#define N 11
int main()
{
unsigned
char a[N] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'a'};
size_t cnt
= 0;
reverse(a,
0, N-1);
print(a,
0, N-1);
sort(a,
0, N-1, 1);
print(a,
0, N-1);
sort(a,
0, N-1, 0);
print(a,
0, N-1);
printf(
"---------------\n");
while (smaller_next(a, 0, N-1)) { cnt++; }
printf(
"---------------\n");
print(a,
0, N-1);
printf(
" --- %u ---\n", cnt);
cnt
=0;
while (larger_next(a, 0, N-1)) cnt++;
print(a,
0, N-1);
printf(
" --- %u ---\n", cnt);
return 0;
}

void sort(unsigned char a[], int lo, int high, int order)
{
int i, j;
//insertion sort
for (i=lo+1; i<=high; i++)
{
for (j=i-1; j>=lo; j--)
{
if (a[j+1]<a[j])
swap(
&(a[j+1]), &(a[j]));
}
}
//descending
if (order == 0)
reverse(a, lo, high);
}
void print(unsigned char array[], int lo, int high)
{
int i;
for (i = lo; i<= high; i++)
printf(
"%d ", array[i]);
printf(
"\n");
}
void swap(unsigned char *a, unsigned char *b)
{
unsigned
char t = *a;
*a = *b;
*b = t;
}

void reverse(unsigned char array[], int lo, int high)
{
while (lo < high)
{
swap(
&(array[lo++]), &(array[high--]));
}
}




int smaller_next(unsigned char array[], int lo, int high)
{

int k=high;
int temp;
int j, i;

int low;
for (j = high; j>lo; j--)
if (array[j] < array[j-1])
break;
low
= j-1;
if (low<0) low = 0;

for (j = high; j >= low; j--)
{
k
= j;
for (i = j-1; i >= low; i--)
{
if (array[i] > array[k])
{
temp
= array[k];
array[k]
= array[i];
array[i]
= temp;
sort(array, i
+1, high, 0);
return 1;
}
}
}
return 0;
/*
int i, cur=-1, max, k;
for (i=high; i>lo; i--)
{
if (array[i]<array[i-1])
{
//the digit should be adjusted for getting next smaller number
cur = i-1;
break;
}
}
if (cur == -1)
return 0;

max = INT_MIN;
//find the digit which is the largest of the digits, that are smaller than array[cur]
for (i=cur+1; i<=high; i++)
{
if (array[i]<array[cur])
{
if (array[i]>max)
{
max = array[i];
k = i;
}
}
}
swap(&(array[cur]), &(array[k]));
sort(array, cur+1, high, 0);
return 1;
*/
}
/*
* 第一种算法:稍微快一点
* 要寻找比长整数124653更大的排列,可从该排列的最后一个数字顺序
* 向前逐位考察,当发现排列中的某个数字比它前一个数字大时,如本
* 例中的6比它的前一位数字4大,这说明还有对应更大整数的排列,并
* 标识前一位数字为需要调整的数字(比如这里的4)--这里称为交换位。
* 然后在从这一数字开始直到最后一个数字的系列中,我们应用如下方法:
* 把该排列的数字从最后一位开始顺序作为考察位,当发现考察位大于它前面
* 的某个数字时,则把这两个数字交换,然后对交换位后面的数字进行
* 排列。
*/

/*
* 第二种算法:
* 要寻找比长整数124653更大的排列,可从该排列的最后一个数字顺序
* 向前逐位考察,当发现排列中的某个数字比它前一个数字大时,如本
* 例中的6比它的前一位数字4大,这说明还有对应更大整数的排列。但
* 为了顺序从小到大列举出所有的排列,不能立即调整得太大,如本例
* 中将数字6与数字4交换得到的排列126453就不是排列124653的下一个
* 排列。为了得到排列 124653的下一个排列,应从已经考察过的那部分
* 数字中选出比数字大,但又是它们中最小的那一个数字,比如数字5,
* 与数字4交换。该数字也是从后向前考察过程中第一个比4大的数字。5
* 与4交换后,得到排列125643。在前面数字1,2,5固定的情况下,还应
* 选择对应最小整数的那个排列,为此还需将后面那部分数字的排列顺
* 序颠倒,如将数字6,4,3的排列顺序颠倒,得到排列1,2,5,3,4,
* 6,这才是排列1,2,4,6,5,3的下一个排列。
*/

int larger_next(unsigned char array[], int lo, int high)
{
//第一种算法要比第二种稍微快一点
int i, j, temp, k;

int low;
for (j = high; j>lo; j--)
if (array[j] > array[j-1])
break;
low
= j-1;
if (low<0) low = 0;

for (i=high; i>=low; i--)
{
k
= i;
for (j=i-1; j>=low; j--)
{
if (array[k] > array[j])
{
temp
= array[k];
array[k]
= array[j];
array[j]
= temp;
//sort the numbers after it in descending order
sort(array, j+1, high, 1);
return 1;
}
}
}
return 0;
/*
int i, cur=-1, min, k;
for (i=high; i>lo; i--)
{
if (array[i]>array[i-1])
{
//the digit should be adjusted for getting next larger number
cur = i-1;
break;
}
}
if (cur == -1)
return 0;

min = INT_MAX;
//find the digit which is the smallest of the digits, that are larger than array[cur]
for (i=cur+1; i<=high; i++)
{
if (array[i]>array[cur])
{
if (array[i]<min)
{
min = array[i];
k = i;
}
}
}
swap(&(array[cur]), &(array[k]));
sort(array, cur+1, high, 1);

return 1;
*/

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值