2.1. SINH CÁC DÃY NHỊ PHÂN ĐỘ DÀI N
Mô tả thuật toán
Một dãy nhị phân độ dài
Dễ thấy:
Một dãy nhị phân
độ dài là biểu diễn nhị phân
của một giá trị nguyênnào đó nằm trong đoạn . Số các dãy nhị phân độ dài
số các số tự nhiên
. Ta sẽ lập chương trình liệt kê các dãy nhị phân theo thứ tự từ điển có nghĩa là sẽ liệt kê lần lượt các dãy nhị phân biểu diễn các số nguyên theo thứ tự
.
Ví dụ: Khi
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | |
000 | 001 | 010 | 100 | 011 | 101 | 110 | 111 |
Như vậy dãy đầu tiên
sẽ là cuối cùng
sẽ là đang có và không phải dãy cuối cùng
cần liệt kê thì dãy kế tiếp
sẽ nhận được bằng cách cộng thêm 1
( theo cơ số 2 có nhớ) vào dãy hiện tại.
Ví dụ khi n = 8: | |||
---|---|---|---|
Dãy đang có: | Dãy đang có: | ||
cộng thêm 1: | + 1 | cộng thêm 1: | + 1 |
Dãy mới: | 10010001 | Dãy mới: | 10011000 |
Như vậy kỹ thuật sinh cấu hình kế tiếp từ cấu hình hiện tại có thể mô tả như sau:
- Xét từ cuối dãy về đầu (xét từ hàng đơn vị lên), tìm số 0 gặp đầu tiên
+ Nếu thấy thì thay số 0 đó bằng số 1 và đặt tất cả các phần tử phía sau vị trí đó bằng 0.
+ Nếu không thấy thì thì toàn dãy là số 1, đây là cấu hình cuối cùng
- Dữ liệu vào (Input): nhập từ file văn bản BSTR.INP chứa số nguyên dương n ≤ 100
- Kết quả ra (Output): ghi ra file văn bản BSTR.OUT các dãy nhị phân độ dài n.
BSTR.INP | BSTR.OUT |
---|---|
3 | 000 001 010 100 011 101 110 111 |
Thể hiện thuật toán với C++
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <math.h>
using namespace std;
/**
* đọc chuỗi kí tự được lưu ở dòng 1 của file lưu
* trả về: (kiểu: string)
*/
string readFile()
{
string inputText;
string inpFile = "BSTR.INP.txt";
fstream infile;
infile.open(inpFile);
while (!infile.eof()) // kiểm tra xem đã là kết thúc của file hay chưa
{
getline(infile, inputText); // đọc chuỗi kí tự của một dòng và lưu vào biến được chỉ định
break;
}
infile.close();
return inputText;
}
/**
* hiển thị dãy nhị phân
*
*/
void printArray(int *array, int sizeOfArray)
{
for (int i = 0; i < sizeOfArray; i++)
{
cout << array[i];
}
cout << endl;
}
/**
* khởi tạo mảng ban đầu
* gán giá trị mặc định cho các phần tử trong một mảng
* giá trị mặc định ở bài toán này - 0
*/
void initArray(int *array, int sizeOfArray)
{
for (int i = sizeOfArray - 1; i >= 0; i--)
{
array[i] = 0;
}
}
/**
* triển khai thuật toán - sinh các chuỗi nhị phân có độ dài (n) được lưu trong file
*
*/
void binaryStringEnumeration()
{
string outputFile = "BSTR.OUT.txt";
string inputText = readFile();
// chuyển đổi string -> integer
stringstream geek(inputText);
int inputVal = 0;
geek >> inputVal;
// khởi tạo mảng
int array[inputVal];
initArray(array, inputVal);
// tổng số các chuỗi nhị phân có độ dài n
int numberOfBinaryArrays = pow(2, inputVal);
// hiển thị chuổi ban đầu
printArray(array, inputVal);
// thực hiển tìm kiếm các chuỗi nhị phân tiếp theo
while (numberOfBinaryArrays > 0)
{
// kiểm tra từ cuối lên đầu các số trong chuỗi nhị phân hiện tại
for (int i = inputVal - 1; i >= 0; i--)
{
// nếu số hiện tại là 0 thì tiến hành
if (array[i] == 0)
{
// gán bằng số hiện tại = 1
array[i] = 1;
// thực hiện chuyển hết các số phía số hiện tại về = 0 (vị trí: i + 1 --> vị trí cuối cùng của chuỗi)
for (int j = i + 1; j < inputVal; j++)
{
array[j] = 0;
}
// hiển thị chuỗi mới
printArray(array, inputVal);
break;
}
}
numberOfBinaryArrays--;
}
}
int main()
{
binaryStringEnumeration();
}