折半查找法:
#include <stdio.h>
#include <stdlib.h>
//折半查找函数
int binsearch();
main()
{
int x,s[10] = {1,2,3,4,5,6,7,8,9,10};
printf("Please input the number you want to find.\n");
x = getchar() - '0';
printf("x = s[%d]\n",binsearch(x,s,10));
system("pause");
}
int binsearch(int x,int v[],int n)
{
int low,high,mid;
low = 0;high = n - 1;
while(low <= high){
mid = (low + high) / 2;
if(x < v[mid])
high = mid - 1;
else if(x > v[mid])
low = mid + 1;
else
return mid;
}
return -1;
}
希尔排序(Shell Sort)是插入排序的一种。是针对直接插入排序算法的改进。该方法又称缩小增量排序,
希尔排序基本思想:
先取一个小于n的整数d1作为第一个增量,把文件的全部记录分成d1个组。所有距离为dl的倍数的记录放在同一个组中。先在各组内进行直接插入排序;然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量dt=1(dt<dt-l<…<d2<d1),即所有记录放在同一组中进行直接插入排序为止。
#include <stdio.h>
#include <stdlib.h>
//shell排序法
void shellsort();
main()
{
int i, v[10] = {10,5,2,4,6,8,9,1,3,7};
for(i = 0;i < 10;i++)
printf("%d ",v[i]);
printf("\n");
shellsort(v,10);
for(i = 0;i < 10;i++)
printf("%d ",v[i]);
system("pause");
}
//shellsort函数:按递增顺序对v[0]--v[n-1]排序
void shellsort(int v[],int n)
{
int gap,i,j,temp;
for(gap = n / 2;gap > 0;gap /= 2)
for(i = gap;i < n;i++)
for(j = i - gap;j >= 0 && v[j] > v[j + gap];j -= gap){
temp = v[j];
v[j] = v[j + gap];
v[j + gap] = temp;
}
}
插入排序算法思路:
假定这个数组的序是排好的,然后从头往后,如果有数比当前外层元素的值大,则将这个数的位置往后挪,直到当前外层元素的值大于或等于它前面的位置为止.这具算法在排完前k个数之后,可以保证a[1…k]是局部有序的,保证了插入过程的正确性.
算法描述:
一般来说,插入排序都采用in-place在数组上实现。具体算法描述如下:
1. 从第一个元素开始,该元素可以认为已经被排序
2. 取出下一个元素,在已经排序的元素序列中从后向前扫描
3. 如果该元素(已排序)大于新元素,将该元素移到下一位置
4. 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
5. 将新元素插入到该位置中
6. 重复步骤2
(如果比较操作的代价比交换操作大的话,可以采用二分查找法来减少比较操作的数目。该算法可以认为是插入排序的一个变种,称为二分查找排序。)
- void insertSort(char array[], int n)
- {
- int i,j;
- int temp;
- for(i=0;i<n;i++)
- {
- temp=array[i];
- for(j=i; j>0 && temp<array[j-1];j--)
- array[j]=array[j-1];
- array[j]=temp;
- }
- }
#include <stdio.h>
#include <stdlib.h>
//wϰ3-3
void expand();
main()
{
char s1[10] = "a-gddx-z";
char s2[100];
expand(s1,s2);
printf("%s\n%s",s1,s2);
system("pause");
}
//expand :expand shorthand notation in s1 into string s2
void expand(char s1[],char s2[])
{
char c;
int i,j;
i = j =0;
while((c = s1[i++]) != '\0')
if(s1[i] == '-' && s1[i + 1] >= c){
i++;
while(c < s1[i])
s2[j++] = c++;
}else
s2[j++] = c;
s2[j] = '\0';
}
练习3-4,(这是一个纠结的问题)在数的对二的补码表示中,我们编写的itoa函数不能处理最大的负数,即n等于-2^(字长-1)的情况。请解释其原因。修改函数,使它能在任何机器上运行时都能打印出正确的值。
#include <stdio.h>
#include <string.h>
//itoa 处理最大的负数
#define abs(x) ((x) < 0 ? -(x) : (x))
#define MAXCHAR 100
void reverse (char s[]);
void itoa (int n,char s[]);
main()
{
int i = -2147483648,j;
char s[MAXCHAR];
for (j = 0;j < MAXCHAR;j++)
{
s[j]=0;
}
itoa(i,s);
printf("%s\n",s);
getch();
}
void reverse(char s[])
{
int i,j,c;
for(i = 0,j = strlen(s) - 1;i < j;i++,j--){
c = s[i];
s[i] = s[j];
s[j] = c;
}
}
void itoa(int n,char s[])
{
int sign,i;
sign = n;
i = 0;
do{
s[i++] = abs(n) % 10 + '0';
}while((n /= 10) != 0);
if(sign < 0)
s[i++] = '-';
s[i] = '\0';
reverse(s);
}
另一种版本:
#include <stdio.h>
#include <string.h>
//itoa 处理最大的负数
#define abs(x) ((x) < 0 ? -(x) : (x))
#define MAXCHAR 100
void reverse (char s[]);
void itoa (int n,char s[]);
main()
{
int i = -2147483648,j;
char s[MAXCHAR];
for (j = 0;j < MAXCHAR;j++)
{
s[j]=0;
}
itoa(i,s);
printf("%s\n",s);
getch();
}
void reverse(char s[])
{
int i,j,c;
for(i = 0,j = strlen(s) - 1;i < j;i++,j--){
c = s[i];
s[i] = s[j];
s[j] = c;
}
}
void itoa(int n,char s[])
{
int sign,i;
sign = n;
i = 0;
do{
s[i++] = abs(n) % 10 + '0';
}while((n /= 10) != 0);
if(sign < 0)
s[i++] = '-';
s[i] = '\0';
reverse(s);
}
Exercise 3-4 explanation: There are a number of ways of representing signed integers in binary, for example, signed-magnitude, excess-M, one's complement and two's complement. We shall restrict our discussion to the latter two. In a one's complement number representation, the binary represenation of a negative number is simply the binary representation of its positive counterpart, with the sign of all the bits switched. For instance, with 8 bit variables:
SIGNED BINARY UNSIGNED 25 00011001 25 -25 11100110 230 127 01111111 127 -127 10000000 128
The implications of this are (amongst others) that there are two ways of representing zero (all zero bits, and all one bits), that the maximum range for a signed 8-bit number is -127 to 127, and that negative numbers are biased by (2^n - 1) (i.e. -I is represented by (2^n - 1) - (+I). In our example, so:
Bias = 2^8 - 1 = 255 = 11111111 Subtract 25 = 00011001 Equals = 11100110
In a two's complement representation, negative numbers are biased by 2^n, e.g.:
Bias = 2^8 = 100000000 Subtract 25 = 00011001 Equals = 11100111
In other words, to find the two's complement representation of a negative number, find the one's complement of it, and add one. The important thing to notice is that the range of an 8 bit variable using a two's complement representation is -128 to 127, as opposed to -127 to 127 using one's complement. Thus, the absolute value of the largest negative number cannot be represented (i.e. we cannot represent +128). Since the itoa() function in Chapter 3 handles negative numbers by reversing the sign of the number before processing, then adding a '-' to the string, passing the largest negative number will result it in being translated to itself:
-128 : 10000000 One's complement: 01111111 Subtract 1 : 10000000
Therefore, because (n /= 10) will be negative, the do-while loop will run once only, and will place in the string a '-', followed by a single character, (INT_MIN % 10 + '0'). We can remedy these two bugs in the following way: 1 - change 'while ((n /= 10) > 0)' to 'while (n /= 10)'. Since any fractional part is truncated with integer division, n will eventually equal zero after successive divides by 10, and 'n /= 10' will evaluate to false sooner or later. 2 - change 'n % 10 + '0'' to 'abs(n % 10) + '0'', to get the correct character. EX3_4.C shows the revised function, which will run correctly regardless of the number representation.
/* EX3_4.C ======= Suggested solution to Exercise 3-4 */ #include <stdlib.h> #include <stdio.h> #include <limits.h> void itoa(int n, char s[]); void reverse(char s[]); int main(void) { char buffer[20]; printf("INT_MIN: %d\n", INT_MIN); itoa(INT_MIN, buffer); printf("Buffer : %s\n", buffer); return 0; } void itoa(int n, char s[]) { int i, sign; sign = n; i = 0; do { s[i++] = abs(n % 10) + '0'; } while ( n /= 10 ); if (sign < 0) s[i++] = '-'; s[i] = '\0'; reverse(s); } void reverse(char s[]) { int c, i, j; for ( i = 0, j = strlen(s)-1; i < j; i++, j--) { c = s[i]; s[i] = s[j]; s[j] = c; } }
练习3-5 编写函数itob(n,s,b),将整数n转换为以b为底的数,并将转换的结果以字符形式保存到字符串s中。
#include <stdio.h>
#include <string.h>
//ex3.5
void reverse(char s[]);
void itob(int n,char s[],int b);
main()
{
int n,b;
char s[100];
printf("Please input your number:\n");
scanf("%d", &n);
printf("Please input your base number:\n");
scanf("%d,%d,%d", &b);
itob(n,s,b);
printf("\nThe string is %s",s);
getch();
}
void itob(int n,char s[],int b)
{
int i,j,sign;
if((sign = n) < 0)
n = -n;
i = 0;
do{
j = n % b;
s[i++] = (j <= 9) ? j + '0':j + 'a' - 10;
}while((n /= b) > 0);
if (sign < 0)
s[i++] = '-';
s[i] = '\0';
reverse(s);
}
void reverse(char s[])
{
int i,j,c;
for(i = 0,j = strlen(s) - 1;i < j;i++,j--){
c = s[i];
s[i] = s[j];
s[j] = c;
}
}