在一个整形有序数组中查找具体的某个数,找到返回下标,找不到返回0
思路:在数组中设置左右下标,若左右下标除以二的结果作为中间下标,若中间下标的值为要找的数字,则返回下标,若不是,则更新左右下标和中间下标,直到找到为止,若左右下标的位置已不包含任何元素,则表示其中没有要找的数字,返回0
int Binary_Search(int* ar, int key, int len)
{
int left = 0;
int right = len - 1;
while(left <= right)//等号不能省去,因为二分查找的时候,中间值可能会直接取到要找的数,去掉后就无法找到要找的数了
{
int mid = (left + right) / 2 ;//改变中间下标
if(ar[mid] > key)//需要改变右边界
right = mid - 1;
if(ar[mid] < key)//需要改变左边界
left = mid + 1 ;
if(ar[mid] == key)//找到,返回中间下标
return mid;
}
return 0;
}
一个无序的整型数组,通过冒泡排序的方式排正序/倒序
//冒泡排序
void Bubble_sort(int ar[], int len)
{
for (int i = 0; i < len - 1; i++)//确定趟数
{
for (int j = 0; j < len - 1 - i; j++)//确定每趟对比几对
{
if (ar[j] > ar[j + 1])// > 为正序 < 为倒序
{
int tmp = ar[j + 1];
ar[j + 1] = ar[j];
ar[j] = tmp;
}
}
}
}
数 1到 100 的所有整数中出现多少个数字9
//数数字
int Calculating_figures(int num, int k)
{
int res = 0;
while (num >= k)//当一个整数小于要数的数字,则一定不会再出现那个数字了
{
if (num % 10 == k)//模和除可以逐位的查看一个整数每位的数字是多少
res++;
num /= 10;
}
return res;
}
//输出乘法口诀表
int main()
{
for (int i = 1; i < 10; i++)
{
for (int j = 1; j <= i; j++)
{
printf("%d * %d = %d ", j, i, i*j);
}
printf("\n");
}
return 0;
}
//判断一个数字是否为闰年
int Is_leap_year(int num)
{
return ((num % 4 == 0) && (num % 100 != 0)) || (num % 400 == 0);//注意,能否整除一个数是%,意为:模x的余数为0,可整除
}
//方法一:让循环次数为2-->num/2的范围,减少循环次数
int Is_prime_number(int num)
{
if (num == 2 || num == 1)
return 0;//2不是素数, 1也不是素数
int flag = 1;//标识位,初始值为1,是素数
for (int i = 2; i <= num / 2 ; i++)
{
if (num % i == 0)
{
flag = 0;//当if条件成立,则证明不是素数,flag为0
break;
}
}
return flag;
}
//方法二
//因为偶数一定不是素数,可以先把偶数排除,然后从3-->num/2的范围,并且每次自增2
int Is_prime(int num)
{
int flag = 1;//1表示是素数
if (num == 1 || num == 2 || num % 2 == 0)
return 0;
for (int i = 3; i < num / 2; i += 2)
{
if (num % i == 0)
{
flag = 0;
break;
}
}
return flag;
}
//方法三
//sqrt()函数,求某一个数的平方根,通过计算2-->sqrt(num)之间有无可整除的数字,即可计算出num是否为素数
int Is_prime(int num)
{
int flag = 1;
if (num == 1)//0既不是素数也不是合数
return 0;
for (int i = 2; i <= sqrt(num); i++)
{
if (num % i == 0)
{
flag = 0;
break;
}
}
return flag;
}
一个字符串,实现逆序
//逆序
char* Reverse(char ar[])
{
char* par = ar;
int len = strlen(ar);
int left = 0;
int right = len - 1;
for (int i = 0; i < len / 2; i++)//循环次数应为字符串个数的一半,否则会将已逆序的字符串重新逆序回去
{
char tmp = ar[right];
ar[right] = ar[left];
ar[left] = tmp;
right--;
left++;
}
return par;
}
一句英文,实现单词之间逆序,单词本身不逆序
//从指定位置逆序
char* Reverse(char* arbegain, char* arend)
{
char* parbegain = arbegain;
while (arbegain < arend)
{
char tmp = *arbegain;
*arbegain = *arend;
*arend = tmp;
arbegain++;
arend--;
}
return parbegain;
}
//字符串逆序
char* Reverar(char* ar)
{
int len = strlen(ar);
Reverse(ar, ar + len - 1);//整体逆序
char* parver = ar;//用于返回指针
char* begain = ar;//用于控制逆序字符串的起始位置
char* end = ar;//控制逆序字符串的终止位置
while (*end != '\0')
{
while (*end == ' ')
{
Reverse(begain, --end);//逆序一个单词
end += 2;
begain = end;
}
end++;
}
return parver;
}
求Sn=a+aa+aaa+aaaa+aaaaa的前5项之和,其中a是一个数字
//前n项和
int fun(int num, int key)//先产生第n项的数字
{
int res = 0;
for(int i = 0; i<key;i++)
{
res += num * (int)pow(10, i);
}
return res;
}
int sum_add(int num, int key)//计算前n项的和
{
int tmp = fun(num, key);//产生最大的一个数字
int res = fun(num, key);
for (int i = 0; i < key; i++)
{
res += tmp / 10;//逐项相加
tmp /= 10;
}
return res;
}
1瓶汽水1元,2个空瓶可以换一瓶汽水,给20元,可以喝多少汽水
int bubble_num(int money, int Price)
{
int bubble = money / Price;//设置初始瓶子的个数
int empty = bubble;//初始空瓶子数等于瓶子数
while (empty > 1)
{
bubble += empty / 2;//瓶子数累加
empty = empty / 2 + empty % 2;//空瓶子数计算需要考虑无法除尽
}
return bubble;
}
设计两个int变量,一个从数组左端开始右移,一个从右端开始左移,当寻找到左端为偶数并且右端为奇数的时候,两个数字交换,不满足此条件,满足的一端不动,移动不满足要求的一段
void Odd_even(int* ar, int len)
{
int left = 0;
int right = len - 1;
while (left < right)//数组循环结束条件
{
while (ar[left] % 2 == 0 && ar[right] % 2 != 0)//数组找到可以交换的一奇一偶
{
int tmp = ar[left];
ar[left] = ar[right];
ar[right] = tmp;
}
if (ar[left] % 2 != 0)//左端数字不是奇数则不满足交换条件,右端--
right--;
if (ar[right] % 2 == 0)//右端数字不满足交换条件,左端++
left++;
if (ar[left] % 2 != 0 && ar[right] % 2 == 0)//两端数字都不满足交换条件,左右分别++--
{
right--;
left++;
}
}
}
int main()
{
int ar[8][8] = { 1 };//设置初始为1
for (int i = 1; i < 8; i++)//行数,从第1行开始
{
for(int j = 1; j <= i ; j++)//列数,从第1列开始
{
ar[i][0] = 1;杨辉三角的第0列永远为1
ar[i][j] = ar[i-1][j - 1] + ar[i-1][j];当前元素的值为前一行前一列的值+前一行当前列的值
}
}
for (int i = 0; i < 8; i++)
{
for (int j = 0; j <= i; j++)
{
printf("%d ", ar[i][j]);
}
printf("\n");
}
return 0;
}
牛客网链接link
牛客网链接link
数字矩阵,矩阵的每行从左到右是递增的,矩阵从上到下是递增的,请编写程序在这样的矩阵中查找某个数字是否存在。
//杨氏矩阵
int search_ar(int ar[][4], int x, int y, int key)//x行数,y列数,key要找的数 int ar[][4]二维数组传参
{
int i = 0;
int j = y - 1;//从数组的右上角开始计算
while (i < x && i >= 0 || j < y && j >= 0)//行数和列数都在数组的范围内
{
while (ar[i][j] > key)//当前的数比要找的数大,则一定在下一行
{
j--;
}
while (ar[i][j] < key)//当前的数比要找的数小,则一定在当前行的前列
{
i++;
}
if (ar[i][j] == key)//如果找到了,返回1
return 1;
}
return 0;//没找到,返回0
}
ABCD左旋一个字符得到BCDA
ABCD左旋两个字符得到CDAB
char* ar_loop(char* ar, int time)
{
char* par = ar;
int len = strlen(ar);
while (time)//设置左旋次数
{
//每次只旋转一个字符
char tmp = ar[0];//把当前第一个位置的字符暂存
for (int i = 0; i < len - 1; i++)
ar[i] = ar[i + 1];//剩下的字符逐个前移一位
ar[len-1] = tmp;//把暂存的字符放到\0前
time--;
}
return par;
}
int main()
{
char ar[] = "abcdef";
ar_loop(ar, 3);
printf("%s ", ar);
return 0;
}
//字符串判断旋转
int Is_loop(char* ar, char* ar1)
{
int len_ar = (int)strlen(ar);
int len_ar1 = (int)strlen(ar1);
if (len_ar != len_ar1)//两个字符串长度不等的话,一定不是旋转得到的,返回0
return 0;
for (int time = 0; time < len_ar; time++)//找出所有可能出现的字符串旋转情况
{
while (time)//设置左旋次数
{
//每次只旋转一个字符
char tmp = ar[0];//把当前第一个位置的字符暂存
for (int i = 0; i < len_ar - 1; i++)
ar[i] = ar[i + 1];//剩下的字符逐个前移一位
ar[len_ar - 1] = tmp;//把暂存的字符放到\0前
time--;
}
if (strcmp(ar, ar1) == 0)//每种旋转情况出现后进行比较
return 1;
}
return 0;//所有的情况都比较之后,依然没有相等的情况,说明两个字符串没有旋转关系
}
qsort的模拟实现
注意:模拟实现qsort时,依然使用冒泡排序的方式,但是由于无法知道传入的参数是什么类型,因此只能逐字节进行交换,所以my_qsort传入的参数需要有参数个数和参数的字节数,我们只能通过传入的参数字节数来逐字节进行交换,从而实现冒泡排序
//使用冒泡排序的方式进行排序
void my_qsort(void* base, int num, int width, int(* compare)(const void* elem1, const void* elem2))//my_qsort使用冒泡排序实现
{
for (int i = 0; i < num - 1; i++)//趟数
{
for (int j = 0; j < num - i - 1; j++)//每趟比较的对数
{
if (compar_int((char*)base+ j*width, (char*)base+ (j+1)*width))//返回值为1,交换两个参数
//交换
swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
}
}
}
//交换函数
void swap(char* elem1, char* elem2, int width)
{
while(width)//逐字节进行交换,width代表待排序数组中每个元素所占的字节数
{
char tmp = *elem1;
*elem1 = *elem2;
elem2 = tmp;
elem1++;
elem2++;
width--;
}
}
//比较函数
//比较函数是使用my_qsort的人写的,主要目的是告诉my_qsort函数,待排序数组是以什么样的规则进行排序
//例如现在要进行整型的排序
int compar_int(const void* elem1, const void* elem2)
{
if(*(int*)elem1 > *(int*)elem2)//这里说明待排序数组是整型,以正序的方式进行排序
return 1;
else
return 0;
}
//例如现在要进行short类型排序
int compar_short(const void* elem1, const void* elem2)
{
if(*(short*)elem1 > *(short*)elem2)
return 1;
else
return 0;
}
//例如现在要进行char类型排序
int compar_char(const void* elem1, const void* elem2)
{
if(*(char*)elem1 > *(char*)elem2)
return 1;
else
return 0;
}
//模拟实现strlen函数
size_t my_strlen(const char* string)
{
assert(string != NULL);
//保护参数
const char* par = string;
int count = 0;//设置计数器
while (*par != '\0')
{
count++;
par++;
}
return count;
}
char* my_strcat(char* strDest, char* strsource)
{
assert(strDest != NULL && strsource != NULL);
char* par = strDest;
while (*strDest != '\0') //第一步,找到被拼接字符串的\0
strDest++; //找到了
while (*strsource != '\0') //在被拼接字符串的末尾进行拼接
*strDest++ = *strsource++; //先拼接,指针后加加
if (*strsource == '\0') //最终把\0加到拼接完成的字符串末尾
*strDest = '\0';
return par; //返回最初字符串的开头地址
}
字符串的比较,是通过字符的ASCII码进行比较的
//方法一
int my_strcmp(const char* array1, const char* array2)
{
assert(array1 != NULL && array2 != NULL);
while (*array1 != '\0' && *array2 != '\0' && *array1 == *array2)
{
array1++;
array2++;
if (*array1 > *array2)
return 1;
if (*array1 < *array2)
return -1;
}
//由于存在字符串长度不同的问题,因此需要考虑当字符串长度不同时,如何进行比较
if (*array1 != '\0')//上面的while循环结束时,可能是由于array2结束了,而array1未结束,则此时array1一定大
return 1;
if (*array2 != '\0')//面的while循环结束时,可能是由于array1结束了,而array2未结束,则此时array2一定大
return -1;
return 0;//除了while循环中的情况,和长度不一致的情况,都没有判断出大小,说明字符串是相同的
}
//方法二
int my_strcmp(const char* array1, const char* array2)
{
assert(array1 != NULL && array2 != NULL);
while (*array1 != '\0' || *array2 != '\0')//由于\0的ASCII码值为0,采用或的方法,当一个字符串结束而另一个字符串未结束的时候,\0与字符一定可以比较出结果,就省去了考虑字符串长度的问题
{
if (*array1 == *array2)
{
array1++;
array2++;
}
if (*array1 > *array2)
return 1;
if (*array1 < *array2)
return -1;
}
//当字符串循环结束都没有比较出结果,说明字符串是一样的
return 0;
}
//实现strcpy函数
char* my_strcpy(char* strDestination, const char* strSource)
{
assert(strDestination != NULL && strSource != NULL);
while (*strSource != '\0')
{
*strDestination = *strSource;
strSource++;
strDestination++;
}
if (*strSource == '\0')
*strDestination = '\0';
return strDestination;
}
int main()
{
char ar[] = "abcde";
char ar1[] = "fghi";
my_strcpy(ar, ar1);
//strcpy(ar, ar1);
printf("%s ", ar);
return 0;
}
//模拟实现strstr
int my_strstr(const char* dest, const char* src)
{
const char* left = dest;
const char* end = dest;
const char* src_tmp = src;
while (*end != '\0')//设置结束条件
{
left = end;//修改起始指针的位置
src_tmp = src;//讲查找字符串的指针位置置于初始位置
while (*left != '\0' && *src_tmp != '\0' && *left == *src_tmp)
{
left++;
src_tmp++;
}
if (*src_tmp == '\0')//当查找完成后,查找字符串的指针指向\0,说明查找完成,存在字符串
return 1;
end++;//被查找字符串中不存在所有查找字符串的字符,上诉循环退出,指针++
}
return -1;//整个被查找字符串已查找完成,没有找到字符串的存在,返回-1
}
memcpy由于传入的参数类型未知,因此需要通过逐字节的方式进行拷贝
//实现memcpy
void* my_memcpy(void* dest, const void* src, size_t count)
{
void* par = dest;
while (count)//设置拷贝字节数
{
*(char*)dest = *(char*)src;//进行拷贝
dest = (char*)dest + 1;//设置向后移动一个字节
src = (char*)src + 1;//设置向后移动一个字节
count--;
}
return par;//返回被拷贝数组的首地址
}
memmove与memcpy的区别:memcpy不能保证自己拷贝自己时发生空间重叠时的正确性,而memmove可以确保正确(也是就是说,memmove可以解决指针指向的空间重叠的问题)
void* my_memmove(void* des, const void* src, size_t num)
{
assert(des && src);
void* ret = des;
char* des_tmp = (char*)des;//目标字符串
const char* src_tmp = (char*)src;源字符串
if (des_tmp <= src_tmp || src_tmp + num < des_tmp)//情况2和情况1
{
while (num--)
{
*des_tmp++ = *src_tmp++;
}
}
else//情况2
{
des_tmp += num - 1;
src_tmp += num - 1;
while (num--)
{
*des_tmp-- = *src_tmp--;
}
}
return ret;返回目标字符串首地址
}
完整代码在gitee项目:link