一.冒泡排序
冒泡排序是一种比较排序,通过两两比较而将一个最大的数推向后面,或者将一个最小的数推向前面,外循环定义的每一次排序,只需要冒一个泡(也就是推一个数),下一次就不需要再访问已经排好的这个地方
流程如下:(向前排序)
(1)对数组中的各数据,依次比较相邻的两元素的大小
(2)如果前面的数据大于后面的数据,就交换这两个数据。经过第一轮的多次比较排序后,便可以把最小的数据排好
(3)然后,再用同样的方法把剩下的数据逐一比较,最后便可按照从小到大的顺序排好个数据的排序。
冒泡排序的循环有两种写法,一种是向前冒泡,一种是向后冒泡。
#include<cstdio>
//以下是输出函数
void printfArr(int *m,int n){
for(int i=0;i<n;i++){
printf("%d ",m[i]);
}
printf("\n");
}
//以下向后冒泡函数
void BubbleSortAfter(int *a,int n){
int t;
for(int i=0;i<n-1;i++){
for(int j=0;j<n-i-1;j++){
if(a[j]>a[j+1]){
t=a[j];
a[j]=a[j+1];
a[j+1]=t;
}
}
printf("第%d次向后冒泡排序结果:",i);
printafArr(a,n);
}
}
//以下向前冒泡函数
void BubbleSortFrot(int *b,int n){
int t;
for(int i=0;i<n-1;i++){
for(int j=n-1;j>i;j--){
if(b[j]<b[j-1]){
t=b[j];
b[j]=b[j-1];
b[j-1]=t;
}
}
printf("第%d次向前冒泡排序结果:",i);
printarr(b,n);
}
}
int main(){
int len=10;
int a[10]={2,3,8,4,6,1,9,7,0,5};
BubbleSortAfter(a,len);//向后冒泡
printf("\n");
int b[10]={2,3,8,4,6,1,9,7,0,5};
BubbleSortFrot(b,len);//向前冒泡
return 0;
}
可以结合每一次冒泡的结果来体会执行过程:
二.选择排序
选择排序是通过选择和交换来是实现排序,思路比较直观
流程如下:
(1)首先从从原始数组中选取最小的一个数据,将其和位于第一个位置交换。
(2)接着从剩下的n-1个数据中选取次小的,将其与第二个位置数据交换。
(3)然后这样重复,直到完成最后两个数据交换。最后便完成了对原始数组从小到大的排序。
#include<cstdio>
//以下是输出函数
void printfArr(int *a,int n){
for(int i=0;i<n;i++){
printf("%d ",a[i]);
}
printf("\n");
}
//以下是选择排序函数
void SelectionSort(int *a,int n){
int k,t;
for(int i=0;i<n-1;i++){
k=i;//默认第i位是最小的
for(int j=i;j<n;j++){
if(a[j]<a[k]){
k=j;//将最小数的下标存到k中
}
}
if(k!=i){
t=a[i];
a[i]=a[k];
a[k]=t;
}
printf("第%d次排序结果:",i);
printfArr(a,n);
}
}
int main(){
int len=10;
int a[10]={2,3,8,4,6,1,9,7,0,5};
SelectionSort(a,len);//选择排序
return 0;
}
可以结合每一次排序的结果来理解排序过程:
三.插入排序
插入排序是通过对未排序的数据逐个插入到合适的位置而完成排序工作。插入排序的思路比较简单,使用比较多。
插入排序执行流程:
(1)首先对数组的前两个数据从小到大排序。
(2)接着将第3个数据与排好序的两个数据比较,将第3 个数据插入到合 适的位置。
(4)然后,将第4个数据插入到已排好的前三个数据中。
(4)不断重复上述过程,直到把最后一个数据插入到合适位置。最后,便 完成了对原始数组从小到大的排序。
#include<cstdio>
//以下是输出函数
void printfArr(int *a,int n){
for(int i=0;i<n;i++){
printf("%d ",a[i]);
}
printf("\n");
}
//以下是插入排序函数
void InsertionSort(int *a,int n){
int t,j;
for(int i=1;i<n;i++){
t=a[i];//t储存当前插入的数
j=i-1;//j表示已排好序的最后一个下标
while(j>=0&&t<a[j]){//去找t的插入位置
a[j+1]=a[j];
j--;
}
a[j+1]=t;//将t插入
printf("第%d次排序结果:",i);
printfArr(a,n);
}
}
int main(){
int len=10;
int a[10]={2,3,8,4,6,1,9,7,0,5};
InsertionSort(a,len);
return 0;
}
可以结合每一次排序的结果来理解排序过程:
四.快速排序
快速排序是对冒泡排序进行的改进,具有更高执行效率
排序流程:
(1)首先设定一个分界值,通过分解值将数组分成两部分。
(2)将大于等于分界值的数据集中到数组的右边,小于分解值的数据集中到数组的左边。此时左边部分中各元素小于等于分解值,而右边部分中各元素大于等于分解值。
(3)然后,左边和右边的数据可以独立排序。对于左侧的数据,又可以取一个分解值,将该部分分成左右两个部分,同样左边放置最小值,右边防止最大值。右侧的数组数据也可以做类似的处理。
(4)重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序,再递归将右侧排好序后,整个数组的排序也就完成了。
基本思想:
1.选定中心轴
2.将小于中心轴的放到左边
3.将大于中心轴的放到右边
4.分别对左右子序列重复前三步操作
#include<cstdio>
#include<algorithm>
using namespace std;
int n,a[10001];
void qsort(int l,int r){//快速排序函数
int mid=a[(l+r)/2];//确定中轴
int i=l,j=r;
do{
while(a[i]<mid)i++;//查找左半部分比中轴大的数
while(a[j]>mid)j--;//查找右半部分比中轴小的数
if(i<=j){
swap(a[i],a[j]);//交换
i++;
j--;
}
} while(i<=j);
if(l<j)qsort(l,j);//递归搜索左半部分
if(r>i)qsort(i,r);//递归搜索右半部分
}
int main(){
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
qsort(0,n-1);
for(int i=0;i<n;i++){
printf("%d ",a[i]);
}
return 0;
}
下面是蓝桥杯出现过的快速排序算法:
#include <stdio.h>
int i;
//以下是输出函数
void printfArr(int *a,int n){
for(int i=0;i<n;i++){
printf("%d ",a[i]);
}
printf("\n");
}
//下面是交换函数
void swap(int a[], int i, int j)
{
int t = a[i];
a[i] = a[j];
a[j] = t;
}
//以下是找中心轴函数
int partition(int a[], int p, int r)
{
int i = p;
int j = r + 1;
int x = a[p];//默认第一个数为中心轴
while(1){
while(i<r && a[++i]<x); //左中心轴向右移找到大于中心轴的数
while(a[--j]>x);//右中心轴向左移找到小于中心轴的数
if(i>=j) break;//当左有指针到了相同位置一次排序完成
swap(a,i,j);//交换左右指针指向的数
}
swap(a,p,j);//将中心轴换为j指针指向的数
return j;
}
//以下是递归排序函数
void quicksort(int a[], int p, int r)
{
if(p<r){
int q = partition(a,p,r);//定中心轴
quicksort(a,p,q-1);//中心轴的左边递归继续找中心轴排序
quicksort(a,q+1,r);//中心轴的右边递归继续找中心轴
printf("第%d次排序结果:",i++);
printfArr(a,10);
}
}
int main()
{
int i;
int a[] = {2,3,8,4,6,1,9,7,0,5};
int N = 10;
quicksort(a, 0, N-1);
for(i=0; i<N; i++) printf("%d ", a[i]);
printf("\n");
return 0;
}