冒泡排序法,时间复杂度O(n^2), 相邻元素依次比较, 较大的数字上升, 较小的数字下降,
- (void)sortAction {
//冒泡排序,相邻元素依次比较,把较大的数字上升,较小的数字下降,
int num = 200;
int a[num];
for (int i = 0; i<num; i++) {
a[i] = arc4random()%1000;
}
for (int i = 0; i<num; i++) {
// j是从后往前循环
for (int j = num-1; j>i; j--) {
// 比较相邻元素大小
if (a[j-1] > a[j] ) {
int temp = a[j-1];
a[j-1] = a[j];
a[j] = temp;
}
}
}
for (int i = 0; i<num; i++) {
printf("%d -> ",a[i]);
}
printf("\n 排序完成\n");
}
选择排序法, 时间复杂度O(n^2), 每次从第i个元素之后选出最小值, 然后最小值与a[i]进行交换.
- (void)sortAction {
//选择排序,找到第i个后续元素中的最小值,然后最小值与i进行交换
int num = 200;
int a[num];
for (int i = 0; i<num; i++) {
a[i] = arc4random()%1000;
}
/*
每次子循环把i之后的最小值找出来放到了i的位置,写法上看着更舒服,不如下面直观好理解
for(int i=0;i<num;i++){
for(int j=i;j<num;j++){
if(a[i]>a[j]){
int temp = a[i];
a[i]=a[j];
a[j]=temp;
}
}
}
*/
for (int i = 0; i<num; i++) {
// 找到i之后的最小值
int minIndex = i;
for (int j = i; j<num; j++) {
if (a[minIndex] > a[j]) {
minIndex = j;
}
}
// 交换最小值和i
if (i!=minIndex) {
int temp = a[i];
a[i] = a[minIndex];
a[minIndex] = temp;
}
}
for (int i = 0; i<num; i++) {
printf("%d -> ",a[i]);
}
printf("\n 排序完成\n");
}
直接插入排序, 时间复杂度O(n^2), 假设前i个元素已经排好序了, 对于第i+1个元素,
如果a[i]<=a[i+1], 正是期望的结果, 不做任何处理;
如果a[i]>a[i+1], 从前i个元素中找一个合适的位置插入a[i+1];
- (void)sortAction {
/*直接插入排序,假设前i个元素已经是排好序了,然后处理第i+1个元素,
如果a[i]<=a[i+1], 不做任何处理;
如果a[i]>a[i+1], 在前i个元素中找到一个合适的位置插入此元素
*/
int num = 500;
int a[num];
for (int i = 0; i<num; i++) {
a[i] = arc4random()%(num*10);
}
for (int i = 0; i<num-1; i++) {
// a[i]<=a[i+1],不做处理
// a[i]>a[i+1],在前i中找合适的位置插入
if (a[i]>a[i+1]) {
// 保存第i+1个值
int temp = a[i+1];
// 记录要插入的下标,最后一个大于a[i+1]的元素
int index = i;
// 元素后移,找到第一个小于a[i+1]的值下标,
// 比如1,7,9,5,要处理5的时候,变成1,7,7,9,然后把5放到第一个7的位置
for (int j=i; j>=0; j--) {
if (a[j]<temp) {
break;
}
a[j+1] = a[j];
index = j;
}
a[index] = temp;
}
}
for (int i = 0; i<num; i++) {
printf("%d -> ",a[i]);
}
printf("排序完成\n");
}
三者的时间复杂度都是O(n^2), 但是在实际应用中差别却很大. 在同样对50000个无序数字 进行10次排序,差别能有1-3倍.
细心的你是不是看到了希尔排序, 希尔排序是对直接插入排序的改进, 第一批突破了O(N^2)的算法, 值得单独拎出来一篇文章. 先看懂熟悉了插入排序, 在看希尔排序.