全排列演算法(字典序法、SJT Algorithm 、Heap's Algorithm)
阿新 • • 發佈:2018-12-30
一、字典序法
1) 從序列P的右端開始向左掃描,直至找到第一個比其右邊數字小的數字,即。
2) 從右邊找出所有比大的數中最小的數字,即。
3) 交換與。
4) 將右邊的序列翻轉,即可得到字典序的下一個排列。
5) 重複上面的步驟,直至得到字典序最大的排列,即左邊數字比右邊的大的降序排列。
//字典序法 void dictionary(int length){ int * data = (int *)malloc(sizeof(int) * length); int index; for (index = 0; index < length; ++index) data[index] = index + 1; FILE * fp = fopen("dictionary.txt", "w"); print(fp, data, length); while (nextPermutation(data, 0, length)){ print(fp, data, length); } fclose(fp); free(data); } void swap(int data[], int i, int j){//交換兩個元素 char temp; temp = data[i]; data[i] = data[j]; data[j] = temp; } void reverse(int data[], int first, int last){//翻轉序列 last--; while (first < last){ swap(data, first++, last--); } } int nextPermutation(int data[], int first, int last){ int i, j; i = last - 2; while (i >= 0 && data[i] >= data[i+1]) --i; if (i == -1){ reverse(data, first, last); return 0; } j = last - 1; while (data[j] <= data[i]){ --j; } swap(data, i, j); reverse(data, i + 1, last); return 1; } void print(FILE * fp, int data[], int length){ int index; for (index = 0; index < length; ++index){ fprintf(fp, "%d ", data[index]); } fprintf(fp, "\n"); }
二、SJT Algorithm
初始狀態為。
1) 找到最大的可移動數m(當一個數指向一個比它小的數是,該數就是可移動數)
2) 交換m和m所指向的數
3) 改變所有比m大的數的方向
4) 重複上面的步驟,直至找不到可移動數
//鄰位對換法 void exchange(int length){ Item * data = (Item *)malloc(sizeof(Item) * length); int index, indexOfMax; for (index = 0; index < length; ++index){ data[index].digit = index + 1; data[index].direction = -1; data[index].mobile = (index != 0) ? 1 : 0; } indexOfMax = length - 1; FILE * fp = fopen("exchange.txt", "w"); exPrint(data, length, fp); while (1== data[indexOfMax].mobile || existMobile(data, length)){ if (1== data[indexOfMax].mobile){ int direction = data[indexOfMax].direction; exSwap(data, indexOfMax, indexOfMax+direction); indexOfMax += direction; if ((indexOfMax == 0 && direction == -1) || (indexOfMax == length-1 && direction == 1)){ toMobileorNot(data, length); } } else{ index = findMax(data, length); if (index == -1) break; int direction = data[index].direction; exSwap(data, index, index + direction); index += direction; changeDirection(data, length, index); toMobileorNot(data, length); } exPrint(data, length, fp); } fclose(fp); free(data); } int existMobile(Item data[], int length){//判斷是否存在可移動數 int index; for (index = 0; index < length; ++index){ if (data[index].mobile == 1) return 1; } return 0; } int findMax(Item data[], int length){//找到最大的可移動數 int ans = -1; for (int index = 0; index < length; ++index){ if (data[index].mobile == 1){ if (ans == -1) ans = index; else if (data[index].digit > data[ans].digit) ans = index; } } return ans; } void changeDirection(Item data[], int length, int index){//改變大於可移動數的數的方向 for (int i = 0; i < length; ++i){ if (data[i].digit > data[index].digit){ data[i].direction = -data[i].direction; } } } void toMobileorNot(Item data[], int length){ if (data[0].direction == 1 && data[0].digit > data[1].digit) data[0].mobile = 1; else data[0].mobile = 0; for (int i = 1; i < (length - 1); ++i){ int direction = data[i].direction; if (data[i].digit > data[i+direction].digit) data[i].mobile = 1; else data[i].mobile = 0; } if (data[length-1].direction == -1 && data[length-1].digit > data[length-2].digit) data[length-1].mobile = 1; else data[length-1].mobile = 0; } void exPrint(Item data[], int length, FILE * fp){ for (int index = 0; index < length; ++index){ fprintf(fp, "%d ", data[index].digit); } fprintf(fp, "\n"); } void exSwap(Item data[], int i, int j){ Item tmp = data[i]; data[i] = data[j]; data[j] = tmp; }
三、Heap's Algorithm
以上演算法描述摘自維基百科procedure generate(n : integer, A : array of any): if n = 1 then output(A) else for i := 1; i ≤ n; i += 1 do generate(n - 1, A) if n is odd then j ← 1 else j ← i swap(A[j], A[n])
//Recursive implementation.
#include
#include
#include
FILE * fp = NULL;
int len;
int str2int(char str[]){
int i = 0;
int result = 0;
while (str[i] != '\0'){
result = result * 10 + str[i] - '0';
++i;
}
return result;
}
void print(int data[]){
int i;
for (i = 0; i < len; ++i)
fprintf(fp, "%d ", data[i]);
fprintf(fp, "\n");
}
void swap(int *x, int *y){
int tmp = *x;
*x = *y;
*y = tmp;
}
void generate(int data[], int n){
int i;
if (1 == n)
print(data);
//return;
else{
for (i = 0; i < n; ++i){
generate(data, n-1);
if (n % 2 == 1){
swap(&data[1], &data[n-1]);
} else{
swap(&data[i], &data[n-1]);
}
}
}
}
void heapAlgorithm(int n){
int * data = (int *)malloc(sizeof(int) * n);
int i;
for(i = 0; i < n; ++i)
data[i] = i + 1;
generate(data, n);
free(data);
}
int main(int argc, char **argv){
fp = fopen("heap.txt", "w");
len = (argc > 1) ? str2int(argv[1]) : 10;
clock_t time = clock();
heapAlgorithm(len);
time = clock() - time;
printf("Heap's Algorithm takes %d clocks(%f seconds).\n", time, ((float)time)/CLOCKS_PER_SEC);
return 0;
}