排序算法小结(冒泡排序、简单选择排序、快速排序)
1)冒泡排序bubble_sort
1.原理
假设对a[N]进行排序
依次比较相邻两个数,小数放前,大数放前。
*1 从头开始进行第一轮比较,则得到最后一个位置是所有数中的最大的一个数;
需要比较的次数是N-1,为什么是N-1?因为,总共是N个数,数组下标是从0开始,
如果比较最后两个数据,判断条件:if(a[N-1-1] > a[N-1]),a[N-1]就是数组的最后一个数了,
如果比较次数是N,则执行该论最后一对数据比较时就是if(a[N-1] > a[N]),
众所都知,a[N]中是没有a[N],所以次数会得到一个意想不到的排序,里面会多一个垃圾值,垃圾值的产生就是a[N]。
所以此时必须用N-1。
*2 从头开始进行第二轮比较,则得到倒数第二个位置是所有数中的次最大数;
需要比较的次数是(N-1)-1,为什么是(N-1)-1?因为,解释同上。
*3 从头依次进行第三轮比较,则得到倒数第三个位置是所有数中的次次最大数;
需要比较的次数是N-1-1-1,为什么是(N-1)-1-1?因为,解释同上。
*N-1 依次从头开始比较,直至比较完。
2.代码实现过程
void bubble_sort(int a[], int N) //N是数组a的长度
{
int i, j, tmp;
for(i = 0; i < N-1; i++) //进行比比较的趟数,此时的N-1如果换成N,对程序影响不大,只不过多一次循环而已
{
for(j = 0; j < N-i-1; j++) //开始进行比较,此时的N-i-1不能换成N-i,如果写成N-i,会产生一个垃圾值,解释在*1中
{
if(a[j] > a[j+1])
{
tmp = a[j];
a[j] = a[j+1];
a[j+1] = tmp;
}
}
}
return;
}
2)简单选择排序select_sort
1.原理
假设对a[N]进行排序
假定选一个最小的,依次把后面的数与它进行比较,如果后面的比假定选的最小的还小,则进行交换这两个数。每进行一轮就要找出一个最小的数。
*1 第一轮 假定第一个数是“最小的”,然后依次把后面的数与这个“最小的”的进行比较,如果比这个“最小的”小,首先标记该数为“最小的”,
然后把这个“最小的”与前面的“最小的”交换值,目的是保证第一个数是后面所有数中最小的一个。
*2 第二轮 因为已经知道第一个是最小的,这时从第二个开始寻找最小的,假定第二个是最小的,然后依次把后面的数与这个“最小的”的进行比较,
如果比这个“最小的”小,首先标记该数为“最小的”,然后把这个“最小的”与前面的“最小的”交换值,目的是保证第二个数是后面所有数中最小的一个。
*N 第N轮 步骤同上。
说明 是进行N轮比较还是N-1轮比较,影响不大,原因是:该数组中共有N个数,如果对N-1个数进行了排序处理,即第N-1个数是后面中最小的一个数,
剩余的唯一的第N个数肯定是所有数中最大的,显然它应该放在最后一个位置上,没必要再进行一次循环。如果是进行N轮比较,无非是程序多执行一次循环,
其实实际上这次循环也没有执行,因为在子循环中无法满足循环条件,不能执行循环体。
2.代码实现过程
void select_sort(int a[], int N) //N是数组a的长度
{
int i, j, min, tmp;
for(i = 0; i < N; i++) //从头开始比较
{
min = i; //把第i个数当作最小的,把下标标记为min
for(j = i+1; j < N; j++) //把a[min]依次和它后面的数进行比较
{
if(a[j] < a[min]) //如果后面的某个值比a[min]小
{
min = j; //重新标记最小值下标
}
tmp = a[min]; //交换
a[min] = a[i]; //原来min = i的,如果没有找到比a[min]小的,就不进行交换(如果没找到,i还是和min一样,执行该三条语句没作用)
a[i] = tmp; //只有a[j] < a[min]成立,执行了min = j,这时才能交换(这时min的已经改为j,不再是i了,所以执行才有作用)
} //自己表达欠缺,上面三句表达不够明确,只要自己研读程序,因该能明白其中奥妙
}
return;
}
3)快速排序quick_sort
1.原理
假定对a[N]排序
快速排序使用分治法(Divide and conquer)策略来把一个序列(list)分为两个子序列(sub-lists)。
实现快速排序需要两个函数,分别是:partition()和quick_sort()
函数: int partition(int a[], int i, int j)
函数功能: 把数组分为两段,左段都是比基准小的数,但是左段的数是无序的;右段都是比基准大的数,但是右段的数是无序的。
函数大概实现过程:
*1 选取一个基准(pivot),基准一般选取第一个数a[0];
*2 定义两个变量i、j;
令j从数组尾部向左扫描,直到遇到一个数比基准小的,进行交换。目的是:使比基准小的都放在基准左边。
令i从数组开头向右扫描,直到遇到一个数比基准大的,进行交换。目的是:使比基准大的都放在基准右边。
进行多次循环后,最终i的值就是基准应该放的位置。
原因是:我们假定的基准是数组的第一个数a[0],a[0]也许既不是数组中最大的数也不是数组中最小的数,
也就是基准的位置应该在数组中的某个位置,经过多次循环后,i不断往后递增,当不满足循环条件时,i就停止了,此时i就是基准的位置
(表达欠缺,还需要自己揣摩)
函数: void quick_sort(int a[], int left, int right)
函数功能: 实现排序
函数大概实现过程:
递归的对每一段进行排序
2.代码实现过程
int partition(int a[], int i, int j)
{
int pivot; //基准
pivot = a[i];
while(i < j)
{
while(i < j && a[j] > pivot);
{
j--; //如果右边的比基准大,左移j
}
a[i] = a[j]; //如果遇到了右边的比基准小,和基准交换
while(i < j && pivot <= a[i]);
{
i++; //如果左边的基准小,右移i
}
a[j] = a[i]; //如果遇到了左边的比基准大,和基准交换
}
a[i] = pivot;
return i;
}
void quick_sort(int a[], int left, int right)
{
int pivottag;
if(left < right)
{
pivottag = partition(a, left, right);
quick_sort(a, 0, pivottag-1);
quick_sort(a, pivottag+1, right);
}
return;
}
排序算法小结(冒泡排序、简单选择排序、快速排序)
最新推荐文章于 2022-11-25 01:07:31 发布