选择排序法
思想:从待排序元素中的第一个开始,每一个依次与后面的所有元素作比较,再交换值。
#include <stdio.h>
int main()
{
int arr[10] = {100,29,40,56,78,34,6,2,97,18};
int i,j,t;
for(i=0; i<10; i++) //从第一个开始
{
for(j=i+1; j<10; j++) //依次与后面的每个元素作比较
{
if(arr[i] > arr[j])
{
t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
}
}
for(i=0; i<10; i++)
printf("arr[%d] = %d\n",i,arr[i]);
return 0;
}
优化:
我们不能减少比较次数,但是可以减少交换次数,比而不换,记录下标,与后面所有元素比较完后,再来交换值。
#include <stdio.h>
int main()
{
int arr[10] = {100,29,40,56,78,34,6,2,97,18};
int i,j,t,idx;
for(i=0; i<10; i++) //从第一个开始
{
idx = i; //假设当前元素最小
for(j=i+1; j<10; j++) //依次与后面的每个元素作比较
{
if(arr[idx] > arr[j])
{
idx = j; //有比当前元素更小的,更新最小下标,直到循环结束
}
}
if(idx != i) //idx != i,假设不成立,交换最小下标所在元素和当前元素的值
{
t = arr[i];
arr[i] = arr[idx];
arr[idx] = t;
}
}
for(i=0; i<10; i++)
printf("arr[%d] = %d\n",i,arr[i]);
return 0;
}
冒泡排序
思想:每次从头开始,依次比较相邻元素,再交换。经过一轮比较后,就已经确定好最后一个元素的值。再进行下一轮比较,已经排好的最后一个元素就可以不参加排序了。
图示:
如何确定i,j边界:
N个数,经过一轮比较后,会排好最后一个元素,当只剩两个数未排好时,又经一轮过后,最后一个数排好的同时,第一个数也已经排好,所只需要N-1轮比较就能全部排好。所以外重循环i<N-1(数组元素下标从0开始)。
在一轮比较之中,第一轮需要比较N-1次,每一轮过后,最后一个元素不再参与比较,所以在接下来每一轮中比较次数依次减少一次,所以内重循环比较次数为j < N-1-i;
#include <stdio.h>
#define N 10
int main()
{
int arr[N] = {100,29,40,56,78,34,6,2,97,18};
int i,j,t;
for(i=0; i<N-1; i++)
{
for(j=0; j<N-1-i; j++)
{
if(arr[j] > arr[j+1])
{
t = arr[j];
arr[j] = arr[j+1];
arr[j+1] = t;
}
}
}
for(i=0; i<N; i++)
printf("%d\n",arr[i]);
return 0;
}
优化:
当出现在比完一轮或两轮,这组数据已经变得有序了,后面的每轮比较都不会再交换值了,也就没有意义了,我们就可以提前结束循环。
#include <stdio.h>
#define N 10
int main()
{
int arr[N] = {100,29,40,56,78,34,6,2,97,18};
int i,j,t;
int flag = 1; //定义一个标志
for(i=0; i<N-1; i++)
{
flag = 1;
for(j=0; j<N-1-i; j++)
{
if(arr[j] > arr[j+1])
{
flag = 0; //进入交换,意味着这一轮比较是必要的,则把标记位置为0;
t = arr[j];
arr[j] = arr[j+1];
arr[j+1] = t;
}
}
if(flag)
break; //若flog为1,则意味着这一轮比较没有再交换值,说明已经有序,提前结束循环。
}
for(i=0; i<N; i++)
printf("%d\n",arr[i]);
return 0;
}