1.冒泡排序
冒泡排序指的是,在排序时,每次比较数组中相邻的两个数,将较小的数排在较大的数之前(当然也可以将较大的数排在较小的数之前),故曰 冒泡。
接下来用具体的例子来说明冒泡排序
比如一个 无序数组 9 63 5 9 8 1
初始值 | 9 | 63 | 5 | 9 | 8 | 1 |
第一趟(i=0) | 9 | 63 | 5 | 9 | 8 | 1 |
第二趟(i=1) | 9 | 5 | 63 | 9 | 8 | 1 |
第三趟(i=2) | 9 | 5 | 9 | 63 | 8 | 1 |
第四躺(i=3) | 9 | 5 | 9 | 8 | 63 | 1 |
第五躺(i=4) | 9 | 5 | 9 | 8 | 1 | 63 |
(ps:只写出了一次排序)
第一次排序从第一个数据开始,扫描整个待排序数列,将最大值放在了最后的位置(n-1)
第二次排序中,对剩下的5(n-1)个数据进行排序,将最大值9放到最后的位置(n-2)
继续对剩下的数进行排序.........
从中发现规律,若有n个无序数字,只需进行(n-1)次排序(ps:最后一次排序中将第一个数和第二个数同时排序,因为只剩下最后一个数字),而每次排序中又分为(n-1-i)躺小排序。
故用两个循环来控制大循环和小循环,代码如下:
#include<stdio.h>
int main()
{
int a[10];
int i,j,t,n;
printf("请输入数字个数(小于10):");
scanf("%d",&n);
for(i=0;i<n;i++)/*键盘输入数据 */
scanf("%d",&a[i]);
for(i=0;i<n-1;i++)/*第一趟排序 */
for(j=0;j<n-1-i;j++)/*每一趟排序中的小排序*/
{
if(a[j]>a[j+1])/*如果后一个数比前一个数小,则交换位置*/
{
t=a[j];
a[j]=a[j+1];
a[j+1]=t;
}
}
for(i=0;i<n;i++)\\输出排序后的数字
printf("%d\t",a[i]);
}
2,选择排序
选择排序指每次选择数组中的最小值,将这个最小值与前边没有进行排序的数字进行交换
同样,以9,63,5,9,8,1为例
初始数列 | 9 | 63 | 5 | 9 | 8 | 1 |
第一次 | 1 | 63 | 5 | 9 | 8 | 9 |
第二次 | 1 | 5 | 63 | 9 | 8 | 9 |
第三次 | 1 | 5 | 8 | 9 | 63 | 9 |
第四次 | 1 | 5 | 8 | 9 | 9 | 63 |
假定数组中第一个元素为最小值,遍历后续元素,找到比这个元素小的值,交换数值,最小的值找到,第一次排序完成
第二次排序中,假定第二个元素为最小值,遍历后续元素,找到比它小的值,交换,第二次排序完成。
..........
代码如下:
#include<stdio.h>
int main()
{
int i,j,temp;
int min;
int a[10]={1,6,9,3,5,2,8,4,5,9};
for (i = 0; i < 10 - 1; i++) {
min = i;
for (j = i + 1; j < 10; j++)
if (a[min] > a[j])
min = j;
temp = a[min];
a[min] = a[i];
a[i] = temp;
}
for(i=0;i<10;i++)
printf("%d\t",a[i]);
}
3.插入排序
插入法排序是抽出一个数据把它插在合适的位置,即左边小于它,右边大于它。
以9 6 15 4 2 为例
初始值 | 9 | 6 | 15 | 4 | 2 |
第一次 | 9 | ||||
第二次 | 6 | 9 | |||
第三次 | 6 | 9 | 15 | ||
第四次 | 4 | 6 | 9 | 15 | |
第五次 | 2 | 4 | 6 | 9 | 15 |
(1). 从第二位开始遍历,
(2). 当前数(第一趟是第二位数)与前面的数依次比较,如果前面的数大于当前数,则将这个数放在当前数的位置上,当前数的下标-1,
(3). 重复以上步骤,直到当前数不大于前面的某一个数为止,这时,将当前数,放到这个位置,
(4). 重复以上3步,直到遍历到最后一位数,并将最后一位数插入到合适的位置,插入排序结束。
#include<stdio.h>
int main()
{
int a[10] = { 1,8,9,5,6,5,4,48,44,99 };
int i, j, iPos;
for (i = 1; i < 10; i++)
{
iPos = a[i];
j = i - 1;
while (j >= 0 && a[j] > iPos)
{
a[j + 1] = a[j];
j--;
}
a[j + 1] = iPos;
}
for (i = 0; i < 10; i++)
printf("%d\t", a[i]);
}
4,最后一个快速排序(也称折半排序)
思路如下:
选择一个中间值(一般选数组中间元素),把小于它的数放在左边,大于它的数放在右边,接着对左右两个区间进行同样工作(使用递归) 挖坑填数,分而治之
以一个数组作为示例,取数组中间元素为基准数
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
72 | 6 | 57 | 88 | 60 | 42 | 83 | 73 | 48 | 85 |
初始时i=0,j=9,取出a[4]相当于在a[4]处挖了个坑,
60 | |||||||||
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
72 | 6 | 57 | 88 | 42 | 83 | 73 | 48 | 85 |
从左边开始取值,与中间值比较,如果值比中间值小,则取下一个数组元素与中间值比较,如果左侧取出的值比中间值大,则交换两个互相比较的元素值,右边与其相反。发现I=0时,a[0]>a[4],交换数值,
60 | |||||||||
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
6 | 57 | 88 | 72 | 42 | 83 | 73 | 48 | 85 |
此时,从右边开始比较,j=8时,a[8]<a[0],交换数值
60 | |||||||||
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
48 | 6 | 57 | 88 | 72 | 42 | 83 | 73 | 85 |
接着从左边找大于60的数,i=3时,满足要求,交换数值,
60 | |||||||||
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
48 | 6 | 57 | 72 | 42 | 83 | 73 | 88 | 85 |
从右边找小于60的数,j=5时,满足要求,交换数值
60 | |||||||||
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
48 | 6 | 57 | 42 | 72 | 83 | 73 | 88 | 85 |
..........
重复操作,最后发现60的左边都比60小,右边都比60大
60 | |||||||||
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
48 | 6 | 57 | 42 | 72 | 83 | 73 | 88 | 85 |
接下来对60的左右两个区间进行同样操作,直至有序。
#include<stdio.h>
int sort(int a[],int left,int right)
{
int i,j,mid,t;
i=left;
j=right;
mid=a[(left+right)/2];
do{
while((a[i]<mid)&&(i<right))//从左边找小于中值的数
i++;
while((a[j]>mid)&&j>left)//从右边找 大于中值的数
j--;
if(i<=j)//找到一对值
{
t=a[i];
a[i]=a[j];
a[j]=t;
i++;
j--;
}
}while(i<=j);//如果两边的下标交错就停止
if(left<j)//递归左边
sort(a,left,j);
if(right>i)//递归右边
sort(a,i,right);
}
int main()
{
int arr[10];
int i,n;
printf("请输入数据个数:");
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d",&arr[i]);
sort(arr,0,n-1);
for(i=0;i<n;i++)
printf("%d\t",arr[i]);
}