冒泡排序
选择排序
快排
归并
还有一些线性排序: 计数排序 基数排序等以后再来补充吧!!!
首先,大家得知道一个知识点:有很多同学都不知道max min sort qsort swap 这些常见函数都在#include<algorithm>中;
但是这些头文件,没有 .h 的头文件需要 using namespace std;命名空间,如果你理解不了,我就打个比方,但是这个比方不一定对,只是来理解的:::就是你想用笔在写东西,就需要纸啊,粉笔需要黑板啊(不要钻牛角尖,哈哈!!!)
1、冒泡排序
#include<stdio.h>
int main()
{
int a[10]={55,5,8,9,3,4,11,2,0,7};
for(int i=0;i<10-1;i++){ //这里是10-1 不过也可以是10
for(int j=i+1;j<10;j++){
if(a[i]>a[j]){<span style="white-space:pre"> </span>//从小到大排序
int t=a[i]; //交换两个数字
a[i]=a[j];
a[j]=t;
}
}
}
//多用分行,这样思路就很清晰了
for(int i=0;i<10;i++)
printf("%d ",a[i]);
return 0;
}
理解这个算法:
其实就是从头开始一个一个往后冒泡出去,我建议初学者自己用四个数字举例,用大脑运行一遍就明白了,当然要动笔懂手,不要忘了高中那个良好的打草稿的习惯,我个人认为,这也算是数学,到时候可能还涉及到其他科目呢!!!
而另一种是利用库函数,简化一:
#include<stdio.h>
#include<algorithm> //包含swap函数
using namespace std; //为上一行提供空间
int main()
{
int a[10]={55,5,8,9,3,4,11,2,0,7};
for(int i=0;i<10-1;i++){ //这里是10-1 不过也可以是10
for(int j=i+1;j<10;j++){
if(a[i]>a[j]){
swap(a[i],a[j]); //交换两个数
}
}
}
//多用分行,这样思路就很清晰了
for(int i=0;i<10;i++)
printf("%d ",a[i]);
return 0;
}
简化二:
#include<stdio.h>
#include<algorithm> //包含sort函数
using namespace std; //为上一行提供空间
int main()
{
int a[10]={55,5,8,9,3,4,11,2,0,7};
sort(a,a+10);
for(int i=0;i<10;i++)
printf("%d ",a[i]);
return 0;
}
这里的sort也在上叙头文件中
如果你想排后面九个数字 那就是用 sort(a+1,a+10);
这里就需要你理解数组的指针效果了,a为指向第一个元素的指针,+1指向第二个,以此类推
2、选择排序
#include<stdio.h>
#include<algorithm>
using namespace std;
int main()
{
int a[10]={55,5,8,9,3,4,11,2,0,7};
int k,temp;
for(int i=0;i<9;i++){
temp=a[i];
k=i;
for(int j=i+1;j<10;j++){
if(temp>a[j]){
k=j;
temp=a[j];
}
}
swap(a[i],a[k]);
}
for(int i=0;i<10;i++)
printf("%d ",a[i]);
return 0;
}
这里其实很简单,以第i个位基准,在其后面选最小的与之交换就行了
我还是那句话,自己用四个数字举例,用大脑运行一遍就明白了,这个还是比较简单的
3、快排
快排比较难理解,对于初学者来说,所以开始我建议大家先会用这个在头文件中的函数就好了,因为这个函数写起来就比较多了,用头文件里面的函数比较简洁!!!
首先是很普通的数列排序
#include<stdio.h>
#include<algorithm>
using namespace std;
int cmp(const void *x,const void *y)
{
return *(int *)x-*(int *)y;<span style="white-space:pre"> </span>//表示从小到大排序,如果想大到小,就将前面两个交换就行了
}
int main()
{
int a[10]={55,5,8,9,3,4,11,2,0,7};
qsort(a,10,sizeof(int),cmp);
for(int i=0;i<10;i++)
printf("%d ",a[i]);
return 0;
}
qsort的括号里面就是 以一个数组的开始地址为起始排序位置,一共十个元素,每一个元素的大小为sizeof(int)
当然起始位置可以是a+1,元素多少你可以自己随机而定,元素大小可以是char 的元素,也可以是其他类型的元素
以此为模板;
cmp函数自己另外命名,可以命名为 mycmp 我习惯上命名为cmp
其中(int *)表示强制类型转换为int 型的指针,你可以类比
double x=100.0002;
int y;
y=(int )x;
强制转换为int型;
运行完括号里面之后,剩下* x ,表示一个指针指向一个数字
现在我们来了解结构体快排
#include<stdio.h>
#include<algorithm>
using namespace std;
typedef struct my_score{
char name[10];
int age,grade;
}K;
K a[50];
int cmp(const void *x,const void *y)
{
my_score *A=(my_score *)x;
my_score *B=(my_score *)y;
return A->grade-B->grade;
}
int main()
{
printf("请依次输入名字,年龄,成绩\n\n");
for(int i=0;i<4;i++)
scanf("%s%d%d",a[i].name,&a[i].age,&a[i].grade);
qsort(a,4,sizeof(my_score),cmp);
for(int i=0;i<4;i++)
printf("%-10s %3d %2d\n",a[i].name,a[i].age,a[i].grade);
return 0;
}
这里的排序是不稳定的排序,意思就是如果两个数字相同的话就不知道原来的两个数字在前在后的
然后计算机他是可以区分的开的,然后我们在有必要的时候就来一个稳定的排序
int cmp(const void *x,const void *y)
{
my_score *A=(struct my_score *)x;
my_score *B=(struct my_score *)y;
if(A->grade==B->grade)
return A->age-B->age;
return A->grade-B->grade;
}
这里意思就是如果成绩相同就按年龄来排序
下面就是快排的具体实现,以下借鉴《算法与程序设计》
int deal(int a[],int p,int t)
{
int i=p;
int j=t+1;
int temp=a[p]; //temp作为一个标记
while(1)
{
while(a[++i]<temp)
; //找到>=temp的元素
while(a[--j]>temp)
; //找到<=temp的元素
if(i>=j)
break;
swap(a[i],a[j]);
}
a[p]=a[j];
a[j]=temp; //temp给了a[j],j就是标志temp的所在位置了
return j;
}
void quicksort(int a[],int p,int t){
if(p<t){
int q=deal(a,p,t);
quicksort(a,p,q-1);
quicksort(a,q+1,t);
}
}
其实思想很简单,就是找一个标准,然后以这个标准把比他大的放一边,比他小的放一边,然后这两部分递归再分别以这个思路运行就可以得出结果了
4、归并
下面就是归并排序的具体实现了,以下借鉴《算法与程序设计》
void merge(int a[],int b[],int low.int mid,int high)
{
int s=low,t=mid+1,k=low;
while(s<=mid&&t<=high){ //分开为两半分别排序
if(a[s]<a[t])
b[k++]=a[s++];
else
b[k++]=a[t++];
}
if(s==mid+1) //复制没有排序的部分
for(int i=k;i<=high;i++)
b[i]=a[t++];
else
for(int i=k;i<=high;i++)
b[i]=a[s++];
for(int i=low;i<=high;i++)
a[i]=b[i]; //复制回数组
}
void mergesort(int a[],int b[],int low,int high)
{
if(low<high){ //至少有两个元素
int mid=(low+high)/2;
mergesort(a,b,low,mid);
mergesort(a,b,mid+1,high);
merge(a,b,low,mid,high); //归并
}
}
对于归并排序,我的理解就是先从小的方面排好序之后慢慢归并到一个完整长度的序列
而快排刚好相反,他是先打的方面进行排序之后再进行小部分的排序
堆排序:poj2388
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define father(i) (i>>1)
#define left(i) (i<<1)
#define right(i) (i<<1|1)
#define swap(a,b) {int t=a;a=b;b=t;}
int heap_size;
int a[10010];
void max_heapify(int i)
{
int l=left(i);
int r=right(i);
int largest;
if(l<=heap_size&&a[l]>a[i])
largest=l;
else
largest=i;
if(r<=heap_size&&a[r]>a[largest])
largest=r;
if(largest!=i){
swap(a[i],a[largest]);
max_heapify(largest);
}
}
void build_max_heap()
{
for(int i=heap_size/2;i>=1;i--)
max_heapify(i);
}
void heap_sort()
{
for(int i=heap_size;i>=2;i--){
swap(a[1],a[i]);
heap_size--;
max_heapify(1);
}
}
int main()
{
int n;
//freopen("in.txt","r",stdin);
while(~scanf("%d",&n))
{
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
heap_size=n;
build_max_heap();
heap_sort();
printf("%d\n",a[n/2+1]);
}
return 0;
}