C语言习题——指针运算

C语言习题——指针运算

  • 1、调整数组使奇数全部在偶数前面
  • 2、模拟实现strlen
  • 3、字符串左旋
  • 4、字符串逆序

1、调整数组使奇数全部在偶数前面

C语言习题——指针运算_第1张图片

思路1:

  1. 给定两个下标left和right,left放在数组的起始位置,right放在数组中最后一个元素的位置
  2. 循环进行一下操作
    a. 如果left和right表示的区间[left, right]有效,进行b,否则结束循环
    b. left从前往后找,找到一个偶数后停止
    c. right从后往前找,找到一个奇数后停止
    d. 如果left和right都找到了对应的数据,则交换,继续a,
void swap_arr(int arr[], int sz)
{
	int left = 0;
	int right = sz-1;
	int tmp = 0;


	while(left<right)
	{
     // 从前往后,找到一个偶数,找到后停止
		while((left<right)&&(arr[left]%2==1))
		{
			left++;
		}
     
		// 从后往前找,找一个奇数,找到后停止
		while((left<right)&& (arr[right]%2==0))
		{
			right--;
		}
     
     // 如果偶数和奇数都找到,交换这两个数据的位置
     // 然后继续找,直到两个指针相遇
		if(left<right)
		{
			tmp = arr[left];
			arr[left] = arr[right];
			arr[right] = tmp;
		}
	}
}

思路2:
冒泡有顺序比较相邻元素的特性, 因此用冒泡循环, 每次相邻元素符合偶数在前,奇数在后时,就把他俩交换即可.

#include 

void Sort(int arr[], int sz)
{
	for (int i = 0; i < n - 1; i++)
		for (int j = i + 1; j < n; j++)
			if (arr[i] % 2 == 0 && arr[j] % 2 == 1)
			{
				int tmp = arr[i];
				arr[i] = arr[j];
				arr[j] = tmp;
			}
}

2、模拟实现strlen

思路1: 计数器

size_t my_strlen(const char* str)
{
	int n = 0;
	assert(str);
	while (*str)
	{
		n++;
		str++;
	}
	return n;
}

思路2: 递归

size_t my_strlen(const char* str)
{
	assert(str);
	if (*str == '\0')
		return 0;
	else
		return my_strlen(str - 1) + 1;
}

思路3: 指针 - 指针( == 两指针之间相差元素的个数)

size_t my_strlen (const char * str)
{
        const char *p = str;
        while( *p++ ) ;
        return( p - str - 1 );
}

3、字符串左旋

C语言习题——指针运算_第2张图片
思路1: 设计循环使其可以旋1次,然后让他执行n次

void leftRound(char * src, int time)
{
	int i, j, tmp;
  int len = strlen(src);
  time %= len; //长度为5的情况下,旋转6、11、16...次相当于1次,7、12、17...次相当于2次,以此类推。
	for (i = 0; i < time; i++) //执行k次的单次平移
	{
		tmp = src[0];
		for(j = 0; j < len - 1; j++) //单次平移
		{
			src[j] = src[j + 1];
		}
		src[j] = tmp;
	}
}

这个思路当然可以,但是一次一次转毕竟太麻烦,就不能一次到位么?

思路2: 拼接法,一次到位

void leftRound(char * src, int time)
{
	int len = strlen(src);
	int pos = time % len; //断开位置的下标
	char tmp[256] = { 0 }; //更准确的话可以选择malloc len + 1个字节的空间来做这个tmp
	
	strcpy(tmp, src + pos); //先将后面的全部拷过来
	strncat(tmp, src, pos); //然后将前面几个接上
	strcpy(src, tmp); //最后拷回去
}

这个方法要用到一个数组形成的辅助空间,让人觉得有点不爽,还可以有更好的选择,例如ABCDEFG,左旋3次后变成DEFGABC,有一个特殊的操作方式:

思路3:
先将要左旋的前三个家伙逆序(CBADEFG),然后将后半段也逆序(CBAGFED),最后整体逆序(DEFGABC)即可。

void reverse_part(char *str, int start, int end) //将字符串从start到end这一段逆序
{
	int i, j;
	char tmp;

	for (i = start, j = end; i < j; i++, j--)
	{
		tmp = str[i];
		str[i] = str[j];
		str[j] = tmp;
	}
}

void leftRound(char * src, int time)
{
	int len = strlen(src);
	int pos = time % len;
	reverse_part(src, 0, pos - 1); //逆序前段
	reverse_part(src, pos, len - 1); //逆序后段
	reverse_part(src, 0, len - 1); //整体逆序
}

4、字符串逆序

在这里插入图片描述

/*
思路:该题比较简单,请参考代码
*/
void Reverse(char* str)
{
    char* left = str;
    char* right = str + strlen(str)-1;
    while(left < right)
    {
        char temp = *left;
        *left = *right;
        *right = temp;
        ++left;
        --right;
    }
}


int main()
{
    char str[] = "hello bit";
    //在这里完成下面函数,参数自己设计,要求:使用指针
    Reverse(str);
    return 0;
}


// 注意:如果是在线OJ时,必须要考虑循环输入,因为每个算法可能有多组测试用例进行验证,参考以下main函数写法,
int main()
{
    char str[101] = {0};
    while(gets(str))
    {
        Reverse(str);
        printf("%s\n", str);
        memset(str, 0, sizeof(str)/sizeof(str[0]));
    }
    return 0;
}

你可能感兴趣的:(C语言习题,算法,排序算法,c语言,开发语言,数据结构)