无耻的copy,然后号称原创~~~我稀饭
问题7.2 假设有一个数组,它有n个元素,每一个都不外乎是红、白、蓝3种颜色之一的代号,就用R、W、B代表。这些元素在数组中并没有依同样颜色排在一起的方式来排列,倾斜一个程序把这个元素排成所有蓝色在前,接着是白色,最后是红色的排列方式,不过在写程序时要满足下面的条件:
1. 不能用额外的内存,换句话说,只能在数组之内用互换的方式来完成。
2. 互换两个元素的动作要越少越好
3. 对于每一个元素而言,测试它是红、是白,还是蓝的工作每种颜色最多只能做一次测试。
在这个条件下,请写一个最快的程序。
#include <iostream>
#include <iterator>
#include <algorithm>
#include <string>
using namespace std;
#define BLUE 'b'
#define WHITE 'w'
#define RED 'r'
#define SWAP(x, y) { char temp; \
temp = color[x]; \
color[x] = color[y]; \
color[y] = temp; \
}
void dutch_flag(char *color)
{
int white = 0;
int blue = 0;
int red = 0;
while (red < strlen(color))
{
if (color[red] == RED)
red++;
else if (color[red] == WHITE)
{
SWAP(white, red);
white++;
red++;
}
else
{
SWAP(blue, red);
blue++;
SWAP(white, red);
white++;
red++;
}
}
}
void main()
{
char color[] = {'r', 'r', 'w', 'w', 'b', 'b', 'b', '\0'};
const int size = sizeof color / sizeof *color;
dutch_flag(color);
for (int i = 0; i < size; i++)
cout << color[i] << " ";
cout << endl;
}
可惜啊,可惜,上面这个代码居然存在bug。。。
下面这组用例立马挂掉上面的程序:char color[] = {'r', 'b', 'w', '\0'};
正确的做法原理如下图所示:
正确的代码如下:
#include <iostream>
#include <iterator>
#include <algorithm>
#include <string>
using namespace std;
#define BLUE 'b'
#define WHITE 'w'
#define RED 'r'
#define SWAP(x, y) { char temp; \
temp = color[x]; \
color[x] = color[y]; \
color[y] = temp; \
}
void dutch_flag(char *color)
{
int white = 0;
int blue = 0;
int red = strlen(color) - 1;
while (white <= red)
{
if (color[white] == WHITE)
white++;
else if (color[white] == BLUE)
{
SWAP(white, blue);
white++;
blue++;
}
else
{
SWAP(white, red);
red--;
}
}
}
void main()
{
char color[] = {'r', 'r', 'w', 'b', 'w', 'b', 'b', 'b', 'w', '\0'};
const int size = sizeof color / sizeof *color;
dutch_flag(color);
for (int i = 0; i < size; i++)
cout << color[i] << " ";
cout << endl;
}
当用例为 char color[] = {'r', 'r', 'w', 'b', 'w', 'b', 'b', 'b', 'w', 'r', 'r', '\0'}; 时,不难发现存在多余的swap操作,可以做如下补充:
void dutch_flag(char *color)
{
int white = 0;
int blue = 0;
int red = strlen(color) - 1;
while (white <= red)
{
if (color[white] == WHITE)
white++;
else if (color[white] == BLUE)
{
SWAP(white, blue);
white++;
blue++;
}
else
{
while (white < red && color[red] == RED)
red--;
SWAP(white, red);
red--;
}
}
}
问题7.3 字符串列整数的转换
在平时课本中的atoi()函数范例,通常都不能查出溢出(overflow)的情况,或者是不理会这个情况而给出错误的结果,请修改这个atoi()程序,把转换后的结果用第二个参数返回来。例如,x_atoi(s,*t)就用t返回结果,而函数则指出OVERFLOW(大于最大整数值)、UNDERFLOW(小于最小整数值)、NO_ERROR(正常),为了方便起见,假设使用的机器是用2的补码存储整数,有没有办法查出机器是用1的补码还是2的补码?
题目比较简单
#include <iostream>
#include <iterator>
#include <algorithm>
#include <string>
#include <limits.h>
#include <ctype.h>
using namespace std;
#define OVERFLOW 1
#define UNDERFLOW -1
#define NO_ERROR 0
int x_atoi(char *s, int *result)
{
int digit_value;
int i;
*result = 0;
for (i = 0; isdigit(s[i]); i++)
{
if (*result <= (INT_MAX - (digit_value = s[i] - '0')) / 10)
*result = 10 * *result + digit_value;
else
return OVERFLOW;
}
return NO_ERROR;
}
void main()
{
char *input = "123411111115";
int result;
int ret = x_atoi(input, &result);
if (ret == NO_ERROR)
{
cout << "number = " << result << endl;
}
else if (ret == OVERFLOW)
{
cout << "over flow" << endl;
}
}
问题7.5 无限位数算术
请写一个使用十进制运算,并且可以计算任意位数精确度的正整数加法和乘法的程序