冒泡排序法
冒泡排序法是最简单的一种排序方法他的基本思想就是有一行数字让他们左右相互比较(a<b)谁小或者谁大就往后面拍,如果这个if不成立就不变(这个是看你是从大往小排还是从小往大排),一直排到第n-1<n 个数然后再来几次(次数由你由n个数定,你就排n-1次,因为你排序最差的情况就是最大的数再最后而你又要以最大的排排前面,这个数最多移动四位)
代码
#include <stdio.h>
#define SIZE 5
int maopao(int *);
int main(void)
{
int sz[SIZE] = {6,4,7,1,2};
for (int i = 0; i < 5; i++)
{
printf("%d\n",*(sz + i));
}
maopao(sz);
printf("----------------------------------------\n");
for (int j = 0; j < 5; j ++)
{
printf("%d\n",*(sz + j));
}
return 0 ;
}
int maopao(int *sz)
{
for(int i = 0; i < 4; i++)
{
int n = 0;
int m = 1;
for (int j = m;j < 5;j ++)
{
if ( *(sz + n) < *(sz + j) )
{
int tmp;
tmp = * (sz + j);
* (sz + j) = *(sz + n);
*(sz + n) = tmp;
}
n++;
}
}
return 0;
}
maopao函数里面,最里面的for循环就是指定左右相互比较,外面的for循环式指定排几次
优点
- 简单好理解
- 缺点效率不高
选择排序法
选择排序法的思想也很简单,就是首先找到最小的数字把他放到第一,然后再从接下来的数列中再找到最小的数字在放到第二。依次类推 ,和冒泡排序法一样他的里面的for循环是定义了取最小值,这个数字是n,因为要和最后一个数字作比较,而外面的for循环定义了一共区几次,这个数字是n-1次(n位数字的个数,因为最后一次不用取他的对比数字已经超过数组边界了他自己就是数组边界)
#include <stdio.h>
#define SIZE 8
void xzpx(int *);
int main(void)
{
int sz[SIZE] = {5,3,2,8,5,6,9,0};
for(int i = 0 ; i<8; i++)
{
printf("%d\n", * ( sz + i ) );
}
printf("----------------------------\n");
xzpx(sz);
for(int j = 0;j < 8;j++)
{
printf("%d\n", * ( sz + j ) );
}
return 0;
}
void xzpx(int * sz)
{
int tmp;
for(int i = 0; i < 7; i++)
{
for(int j = i + 1; j < 8; j++)
{
if( *(sz + i) > *(sz + j) )
{
tmp = *(sz + i);
*(sz + i) = *( sz + j );
*(sz + j) = tmp;
}
}
}
}
~
优点:简单
缺点:不稳定
插入排序法
插入排序法就是从第1个元素开始(就是外层循环),像前面比较大的排前面或者小的排前面,然后我们假定它已经按顺序排好,然后我们再到第二个元素,再用第二个元素和前面一个的元素比谁打排前面或者谁小排前面,比完后我们再拿这个数(有可能已经改变了位子)再往前面比只到它出现再适合的位子,依次类推。
代码
#include <stdio.h>
#define SIZE 10
void insertion_sorting(int *);
int main(void)
{
int arry[SIZE] = {5,2,7,4,1,7,4,9,10,3};
int i;
for(i = 0;i < 10;i++)
{
printf("%d\n",*(arry + i));
}
printf("---------------------\n");
insertion_sorting(arry);
for(i = 0;i < 10;i++)
{
printf("%d\n",*(arry + i));
}
return 0;
}
void insertion_sorting(int *arry)
{
int i,j,n,tmp;
for(j = 1;j <= SIZE;j++)
{
n = 0 ;
for(i = j-1; i >= 0;i--)
{
if(*(arry + i) < *(arry + j - n) )
/*判断前面一个元素是否大于后面的元素,如果大于就说明顺序准确执行else就是break,
如果小于就交换顺序,再拿这个元素和前面所
有的元素相比(注意这时候他的元素顺序就已经
改变了,如何确定这个元素正确的位子我们就用
变量n,每交换一次n就+1让源元素减去他如果到
正确的位子我们就会执行else也就是break)*/
{
tmp = *(arry + i);
*(arry + i) = *(arry + j - n);
*(arry + j - n) = tmp;
n++;
}
else
{
break;
}
}
}
}
~
快速排序法
首先我们有一个无规则数组S,分以下4步执行快速排序
1,如果S中是0或者1返回
2,任取S中任一元素当v成枢纽元(pivot)
注意没有经过充分考虑的选择是将第一个元素作为枢纽元,我们建议使用数组最左边的元素和最右边的元素还有最中间的元素取中位数当成枢纽元
3,将数组分成2个集合,左边的集合(S1)元素都是小于枢纽元的元素,右边的集合(S2)都是大于枢纽元的集合
4,对S1和S2进行快速排序
以上只是大概的步骤,具体的分割策略有一种非常的好用,就是创建2个变量(i和j)分别指向数组最左边元素的下标和最右边元素的下标,然后i和j向中间移动,如果i遇到小于枢纽元的元素略过,遇到大于枢纽元的元素在此元素上停着,然后j同理,向左移动,遇到大于枢纽元的元素略过继续向左移动,遇到小于枢纽元的元素就停住,此时i和j都停在不同的元素上,然后交换他们,只到i和j交错才停止,最后交换i和枢纽元的位置即可,比如我们有一组元组8,1,4,9,0,3,5,2,7,6
一.首先我们要选择枢纽元,取第一个元素8和中间的元素0/3再取最右边的元素6,取他们的中位数6为枢纽元
二.然后创建i和j元素指向数组的最左边和最右边的元素下标,但是最右边是6所以往左移动一格指向7,此时i=1,j=7
三,i和j都向中间移动,i遇到大于枢纽元(6)的元素停止移动,j遇到小于枢纽元的元素停止移动,此时i和j分别停止在8和2上,然后i和j交换值得到一下的新元素2,1,4,9,0,3,5,8,7,6后面的步骤省略最后得到2,1,4,5,0,3,9,8,7,6此时i指向5,j指向9,他们还没有交错就继续往中间移动,最后i等于9,j等于3他们交错了,然后移动i和枢纽元的位置得到最后结果