⚠️图片使用拍摄方式且主要用于个人学习记录 小白记录贴 如果有大神能够指出我的错误点
感激不尽
学习资料:左神网课视频
(当时电脑没有网络所以使用手机编辑本文章)不介意可以继续食用
原思路来自左神的网课(原代码使用java)
想尝试用c语言实现
问题:有一个无序的数组,需要将其按照从小到大的排序输出,由此写出一个程序实现这种功能。
总体的算法思路是:依次将数字与后面所有数字进行比较,并且找出其中最小的数字与前面的数字进行交换,已经实现交换的数字不在处理的范围之内。
以下是算法雏形:
一.创建这样一个数组
想要实现一个输入任意数量元素的数组(暂时不考虑内存溢出的情况),都能排序成功之后输出。
(其实这样还需要获取输入,等到精细化的时候我们再来改进。)
于是使用了sizeof函数进行数组长度的计算。
二.实现数字之间的比较:使用了if语句进行比较
但是没有将x,y与数组中的数字联系起来,如何实现呢?将比较量改成array。
由此就牵涉到数组元素的引用,这里使用下标法。
先定义有最小值,再假设这个值在第零个位置,然后我们再把这个定义的最小值与后面所有值比大小,如果后面有值比它小,就讲小的值更新到这个最小值里面存储,再实现最小值与其他某个跟他比较的数字的交换。
下一步寻找最小数的位置在哪里,如果需要交换位置就交换位置。
-交换实现:需要一个临时变量来存储实现交换
第一步实现之后的整体代码:
运行结果:
算法雏形实现后进行下一步:循环处理实现算法。
结果:12534
问题出在哪里?
我没有将int min放入循环之中。尝试将其放入循环之中。
输出变成了15234 问题在于不清晰min是什么下标,混淆了min了array[min]
错误的地方在于范围画错 以及使用了变量min而不是数组形式进行交换,那么结果就不会是数组间元素的交换而是min和数组间元素的交换,就无法实现想要的结果。
修改之后及输出结果:
后来在查阅资料后,另一种写法:
注明:对于循环的理解,在本代码中外for循环一次,内for循环九次。
想实现打印出来每次交换后的数组,且美观该怎么做呢?多使用printf函数。
新问题:为什么定义min=0在外面的结果会有问题?
问题代码
#include<stdio.h>
int main()
{
int arr[5] = {5,4,3,2,1};//定义数组长度
int i,min,j,k,t,u;
j = i = k = 0;
min = 0;//问题所在
for (i = 0; i < 5; i++)//从第一个元素开始
{
/*!!!!假设最小的位置就是i处,
为什么只能是i而不是0?
涉及到定义变量的范围,
因为下一次循环还是在这一步开始,
然后最后的结果是min和i的值相等所以得是它,
倘若这个式子拿出来在外面定义为0,
会发现结果是12463原因是什么?*/
for (j = i+1; j < 5 ; j++)//i之后的元素之间遍历
{
if (arr[j] < arr[min]) //找出最小值然后标记它的位置
{
min = j;//发现最小的位置为j
}
}
t = arr[i];
arr[i] = arr[min];
arr[min] = t;
/*!!!重点在于交换的理解,
这个交换基于外循环存在的,
因为是外循环的数和内循环的数进行比较,
最后的结果呈现在外循环交换。*/
printf("第%d次循环:",i+1);//打印结果帮助发现问题
for (u = 0; u < 5; u++)
{
printf("%d", arr[u]);//打印出排序之后的数组
}
printf("\n");
}
printf("最终结果: ");
for (k = 0; k < 5; k++)
{
printf("%d", arr[k]);//打印出排序之后的数组
}
}
运行结果
再看正确代码
#include<stdio.h>
int main()
{
int arr[5] = {5,4,3,2,1};//定义数组长度
int i,min,j,k,t,u;
j = i = k = 0;
for (i = 0; i < 5; i++)//从第一个元素开始
{
min = i;
/*!!!!假设最小的位置就是i处,
为什么只能是i而不是0?
涉及到定义变量的范围,
因为下一次循环还是在这一步开始,
然后最后的结果是min和i的值相等所以得是它,
倘若这个式子拿出来在外面定义为0,
会发现结果是12463原因是什么?*/
for (j = i+1; j < 5 ; j++)//i之后的元素之间遍历
{
if (arr[j] < arr[min]) //找出最小值然后标记它的位置
{
min = j;//发现最小的位置为j
}
}
t = arr[i];
arr[i] = arr[min];
arr[min] = t;
/*!!!重点在于交换的理解,
这个交换基于外循环存在的,
因为是外循环的数和内循环的数进行比较,
最后的结果呈现在外循环交换。*/
printf("第%d次循环:",i+1);//打印结果帮助发现问题
for (u = 0; u < 5; u++)
{
printf("%d", arr[u]);//打印出排序之后的数组
}
printf("\n");
}
printf("最终结果: ");
for (k = 0; k < 5; k++)
{
printf("%d", arr[k]);//打印出排序之后的数组
}
}
如果没有min = i,那么交换就会持续进行下去,知道循环结束。
而设置了min = i,最小值就变更为交换之后的arr[i](也是实际结果上的最小值)
看代码可以发现没有进行条件判断arr[min]就和arr[i]进行交换了,因为前面,min = i 保证了每一项都比较到了,所以不需要条件判断,去掉之后就相当于少了条件判断,所以会一直交换下去。
证明选择排序不稳定
总结:
时间复杂度O(n2)
估计时间复杂度只用把最耗时间的语句估计出来即可。
空间复杂度:额外使用的空间,题目和变量不在考虑范围。
选择排序不稳定:相等的两个数可能进行位置交换。
——————————————————以下是体会————————————————————
在初看这个算法的时候感觉很好理解,但还是出现了一些问题,问题主要出在我c语言的使用上不熟悉导致没能实现精准实现想法。不过没关系,正是经过这一次的训练,我加深了对于for循环的理解和对于赋值运算的理解。实践出真知!继续加油!