一、一维数组最值(最大值max、最小值mix)
思路:
- 定义一个变量比如max,赋值为数组第一个元素。max=arr[0];
- 循环遍历数组。
- 判断max和arr[i]的值,如果arr[i]大于max,则max=arr[i];
- 直至循环结束,打印max的值。
图示:
代码: 求数组最大值
int arr[10] = { 1,6,3,99,55,66,13,64,200,111 };
int max = arr[0];// 赋值为数组第一个元素。
int i = 0;
//sizeof(arr)/sizeof(arr[0]) 获取数组元素个数
for (i = 1; i < sizeof(arr)/sizeof(arr[0]); i++)
{
if (arr[i] > max) // 如果arr[i]大于max,则max=arr[i];
{
max = arr[i];
}
}
printf(“Max:%d\n”, max);
打印结果:Max:200
那如何得到数组中最小值呢?
二、一维数组逆序
思路:
- 定义两个变量,一个赋值为下标0,一个赋值为最大下标值(元素个数-1)。
- 循环进行收尾交换。
- 循环次数为(数组元素个数/2)。
图示:
代码:
int arr[10] = { 1,2,3,4,5,11,12,13,14,15 };
int i = 0, j = 0;
int tmp = 0;
int size = sizeof(arr) / sizeof(arr[0]);
j = size - 1;//最大小标
for ( i = 0; i < size / 2; i++,j--)
{
//首位交换
tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
// 循环打印数组中的值
for ( i = 0; i < size; i++)
{
printf("%d ", arr[i]);
}
打印结果:15 14 13 12 11 5 4 3 2 1
三、一维数组中出现频率最高的元素
思路:
- 用每一个元素都从头到尾与所有元素进行比较,出现相同的则count+1。
- 用max记录最大的那个count,用number记录出现频率最高的值。
- 需要使用到双层嵌套循环,第一层循环控制元素值;
- 第二层循环计算元素出现次数;
图示:
依次类推循环
代码:
int arr[10] = { 1,4,8,3,6,8,9,9,1,8 };
int i, j;
int tmp, count = 0;//临时记录每一轮的值和每一轮的值出现的次数
Int max = 0;//记录最高次数
int number = 0;//记录最高次数出现的值
int size = sizeof(arr) / sizeof(arr[0]);
for ( i = 0; i < size; i++)
{
tmp = arr[i];//控制每一轮计算个数的元素值。
count = 0;//每轮开始前计数器清零
for ( j = 0; j < size; j++)
{
//将tmp与数组中每一个元素比较并进行count计数
if (tmp == arr[j])
{
count++;//相同则计数器+1
}
}
if (max < count)//记录最高次数
{
max = count;//记录出现多少次
number = tmp;//记录最多的数字
}
}
printf("number:%d,出现了%d次\n", number, max);
打印结果:number:8,出现了3次
四、删除指定值。
如:
int arr[10] = {11,20,2,5,98,11,101,55,6,10};
int number = 11; // 指定被删除的值
上述数组中又两个11,删除后:
arr元素最终为:20,2,5,98,101,55,6,10
注意:数组大小不会变,即使11被删除,但是数组元素个数还是有10个。
思路: 循环变量数组,遇到与number相同的,就再循环将后面的元素前移动覆盖 。
图示:
代码:
int arr[10] = { 11,20,2,5,98,11,101,55,6,11 };
int number = 11;
int i = 0, j = 0;
int size = sizeof(arr) / sizeof(arr[0]);
for ( i = 0; i < size; i++)
{
if (number == arr[i])//找到了要删除的元素
{
//后面的元素往前移动
for ( j = i; j < size-1; j++)
{
arr[j] = arr[j+1];//注意,这里会将数字范围外的不确定的元素赋值过来
}
arr[size - 1] = -1;//每移动一次,可以将最后一个位置重新赋值。
}
}
//循环打印
for (i = 0; i < size; i++)
{
printf("%d ", arr[i]);
}
打印结果:20 2 5 98 101 55 6 -1 -1 -1
五、新增元素
将一个给定的值,新增到一个有序数组中(前提,数组空间足够,不考虑越界)。
如:int arr[10] = {1,2,5,6,8,10,15,17,18}; // 10个空间,9个值,留一个新增
int insert = 9;
新增后arr则为:1 2 5 6 8 9 10 15 17 18
思路:
-
先找到要插入的位置(下标)。
将insert值,一一比较,找到下标
-
将目标位置(下标)往后的所有值,集体往后移动一个位置
移动要注意覆盖问题,所以要从最后一个元素往后移动。
代码:
int arr[10] = { 1,2,5,6,8,10,15,17,18 };
int insert = 9;
int i = 0;
int size = sizeof(arr) / sizeof(arr[0]);
Int flag = size-1;//默认插入到最后面
//先找到9应该插入到哪个位置,为了防止越界,预留出一个位置
for ( i = 0; i < size-1; i++)
{
if (insert <= arr[i])//如果找到了位置,则记录
{
flag = i;
break;
}//如果没有找到位置,表示insert是已有序列中最大值,则插入到最后面
}
if (flag == size-1)//插入到最后就直接赋值
{
arr[flag] = insert;
}
else
{
//先将目标位置空出来,后面的序列往后移动
for ( i = size-1; i >= flag; i--)
{
arr[i] = arr[i - 1];
}
arr[flag] = insert;//空出来之后再赋值
}
//循环打印
for ( i = 0; i < size; i++)
{
printf("%d ", arr[i]);
}
打印结果:1 2 5 6 8 9 10 15 17 18
六、排序:将一个乱序数组,升序排序
- 冒泡排序: 两个数比较大小,较大的数下沉,较小的数冒起来。
- 比较相邻的两个数据,如果第二个数小,就交换位置;
- 从后向前两两比较,一直到比较最前两个数据。最终最小数被交换到起始的位置,这样一轮下来最小的值就交换到了数组的一个位置。
- 继续重复上述过程,依次将第2.3…n-1个最小数排好位置。
图示:
代码:
int arr[8] = { 42,20,17,13,28,14,23,15 };
int size = sizeof(arr) / sizeof(arr[0]);
int i, j, tmp;
for ( i = 0; i < size-1; i++)//需要冒泡的次数,每次冒泡出最小的值
{
for (j = size-1; j > i; j--)//注意循环次数,冒泡出去的元素就不用再比较了
{
if (arr[j] < arr[j-1])//后一个比前一个小,就交换
{
tmp = arr[j];
arr[j] = arr[j - 1];
arr[j - 1] = tmp;
}
}
}
//循环打印
for (i = 0; i < size; i++)
{
printf("%d ", arr[i]);
}
打印结果:13 14 15 17 20 23 28 42
- 选择排序: 选择最小的一个与目标位置进行交换。
- 在长度为N的无序数组中,第一次遍历n-1个数,找到最小的数值与第一个元素交换
- 第二次遍历n-2个数,找到最小的数值与第二个元素交换;
- …
- 第n-1次遍历,找到最小的数值与第n-1个元素交换,排序完成。
图示:
int arr[8] = { 42,20,17,13,28,14,23,15 };
int size = sizeof(arr) / sizeof(arr[0]);
int i, j, tmp, minIndex;
for ( i = 0; i < size-1; i++)
{
minIndex = i;
for ( j = i+1; j < size; j++)
{
if (arr[i] > arr[j])//找到最小下标的位置
{
minIndex = j;
}
}
if (minIndex != i)//如果最小的下标不是当前的下标,则交换
{
tmp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = tmp;
}
}
//循环打印
for (i = 0; i < size; i++)
{
printf("%d ", arr[i]);
}
打印结果:13 14 15 17 20 23 28 42
- 插入排序:
在要排序的一组数中,假定前n-1个数已经排好序,现在将第n个数插到前面的有序数列中,使得这n个数也是排好顺序的。如此反复循环,直到全部排好顺序。
图示:
int arr[8] = { 42,20,17,13,28,14,23,15 };
int size = sizeof(arr) / sizeof(arr[0]);
int i, j, tmp;
for ( i = 0; i < size-1; i++)
{
for ( j = i+1; j > 0; j--)
{
if (arr[j] < arr[j-1])
{
tmp = arr[j];
arr[j] = arr[j - 1];
arr[j - 1] = tmp;
}
else//注意:如果后一个比前一个不小,不用再继续循环,因为前面都是有序的
{
break;
}
}
}
//循环打印
for (i = 0; i < size; i++)
{
printf("%d ", arr[i]);
}
打印结果:13 14 15 17 20 23 28 42
总结:数组应用旨在训练童鞋们对数组的熟练运用,在脑海中要有一个空间思维,想象着各个元素之间的交换,移动,覆盖等;并注意访问越界问题。
上示例若能理解清楚并实现,表示对数组的理解已经达到了一定的高度。
练习:
1、从键盘中输入一个字符串,统计其字母(a~z ,A~Z)和数字(0~9)的个数。
2、从键盘中输入一个字符串(全数字),将其转换为整数后输出,“123”->123。
3、输入两个字符串,进行比较,如果字符全一致则输出相等,否则输出第一个不同字符的差。
4、他手里握着一叠扑克牌:A,2,....J,Q,K 一共13张。
他先自己精心设计它们的顺序,然后正面朝下拿着,开始表演。
只见他先从最下面拿一张放到最上面,再从最下面拿一张翻开放桌子上,是A;
然后再从最下面拿一张放到最上面,再从最下面拿一张翻开放桌子上,是2;
......如此循环直到手中只有一张牌,翻开放桌子上,刚好是K。这时,桌上牌的顺序是:
A,2,3,4,5,6,7,8,9,10,J,Q,K (可用0表示10)请你计算一下,小明最开始的时候手里牌的顺序是怎样的。