
在PTA例子中的体现:

一、冒泡排序

//1:没有优化的冒泡排序
#include <iostream>
#define MAXN 100001
using namespace std;
int a[MAXN];
void Bubble_Sort(int* a,int N){
//N-1趟
for(int k=N-1;k>0;k--){
for(int i=0;i<k;i++){
if(a[i]>a[i+1]){
int tmp=a[i];
a[i]=a[i+1];
a[i+1]=tmp;
}
}
}
}
//2:优化后的冒泡排序
#include <iostream>
#define MAXN 100001
using namespace std;
int a[MAXN];
void Bubble_Sort(int* a,int N){
//N-1趟
for(int k=N-1;k>0;k--){
int flag=0;
for(int i=0;i<k;i++){
if(a[i]>a[i+1]){
int tmp=a[i];
a[i]=a[i+1];
a[i+1]=tmp;
flag=1;
}
}
if(!flag) return;
}
}
二、插入排序

#include <iostream>
#define MAXN 100001
using namespace std;
int a[MAXN];
void Insert_Sort(int* a,int N){
int j;
for(int i=1;i<N;i++){
int tmp=a[i];
for(j=i-1;j>=0;j--){
if(a[j]>tmp) a[j+1]=a[j];//往后挪
else break;
}
a[j+1]=tmp;//一定要一开始就存一下a[i],不然第一次挪位置a[i]就丢了
}
}
三、希尔排序

#include <iostream>
#define MAXN 100001
using namespace std;
int a[MAXN];
void Shell_Sort(int* a,int N){
int j,D,Si;
int Sedgewick[] = {929, 505, 209, 109, 41, 19, 5, 1, 0};
for(Si=0;Sedgewick[Si]>=N;Si++);
/* 初始的增量Sedgewick[Si]不能超过待排序列长度 */
for(D=Sedgewick[Si];D>0;D=Sedgewick[++Si]){
for(int i=D;i<N;i++){
//每次第0张已经在手上,从第D张开始
int tmp=a[i];
for(j=i-D;j>=0;j-=D){
//第D张前面一张开始比较
if(a[j]>tmp){
a[j+D]=a[j];
}else break;
}
a[j+D]=tmp;
}
}
}
四、选择排序

#include <iostream>
#define MAXN 100001
using namespace std;
int a[MAXN];
void Select_Sort(int* a,int N){
for(int i=0;i<N;i++){
//FindMin
int min=a[N-1],minId=N-1;
for(int j=i;j<N;j++){
if(a[j]<min){
min=a[j];
minId=j;
}
}
//SwapMin
int t=a[minId];
a[minId]=a[i];
a[i]=t;
}
}
五、堆排序

#include <iostream>
#define MAXN 100001
using namespace std;
int a[MAXN];
//没有哨兵,a[i]中i是从0到N-1
void PerDown(int i,int N){
int tmp=a[i];
int parent,child;
for(parent=i;(parent*2+1)<N;parent=child){
child=parent*2+1;
if((child!=N-1) && a[child+1]>a[child]){
child++;
}
if(a[child]>tmp) a[parent]=a[child];
else break;
}
a[parent]=tmp;
}
void Heap_Sort(int* a,int N){
//1:Build MaxHeap
for(int i=N/2;i>=0;i--){
PerDown(i,N);
}
for(int i=N-1;i>0;i--){
//2:swap Max to the end
int t=a[i];
a[i]=a[0];
a[0]=t;
//3:adjust MaxHeap
//改变一个点只会改变一条路径
PerDown(0,i);
}
}
六、归并排序
Merge函数:实现两个内部有序的子序列的归并

//1:递归版
#include <iostream>
#define MAXN 100001
using namespace std;
int a[MAXN];
//两个有序子列的归并
void Merge(int* A,int* TmpA,int Left,int Right,int RightEnd){
int LeftEnd=Right-1;
int num=RightEnd-Left+1;
int TmpA_p=Left;
while ( Left<=LeftEnd && Right<=RightEnd){
if(A[Left]<A[Right]) TmpA[TmpA_p++]=A[Left++];
else TmpA[TmpA_p++]=A[Right++];
}
while(Left<=LeftEnd){
TmpA[TmpA_p++]=A[Left++];
}
while(Right<=RightEnd){
TmpA[TmpA_p++]=A[Right++];
}
for(int i=0;i<num;i++,RightEnd--){
A[RightEnd]=TmpA[RightEnd];
}
}
//分而治之
void MSort(int* A,int* TmpA,int Left,int RightEnd){
int center;
if(Left<RightEnd){
center=(Left+RightEnd)/2;
MSort(A,TmpA,Left,center);
MSort(A,TmpA,center+1,RightEnd);
Merge(A,TmpA,Left,center+1,RightEnd);
}
}
void Merge_Sort(int* a,int N){
int* TmpA=new int[N];
if(TmpA){
MSort(a,TmpA,0,N-1);
}
else printf("空间不足\n");
}

//2:非递归版
#include <iostream>
#define MAXN 100001
using namespace std;
int a[MAXN];
void Merge1(int* A,int* TmpA,int Left,int Right,int RightEnd){
int LeftEnd=Right-1;
int num=RightEnd-Left+1;
int TmpA_p=Left;
while ( Left<=LeftEnd && Right<=RightEnd){
if(A[Left]<A[Right]) TmpA[TmpA_p++]=A[Left++];
else TmpA[TmpA_p++]=A[Right++];
}
while(Left<=LeftEnd){
TmpA[TmpA_p++]=A[Left++];
}
while(Right<=RightEnd){
TmpA[TmpA_p++]=A[Right++];
}
//Merge1不用做Merge中将元素贴回原数组A的这一步
//归并结果存储在TmpA中
/*for(int i=0;i<num;i++,RightEnd--){
A[RightEnd]=TmpA[RightEnd];
}*/
}
void Merge_pass(int* A,int* TmpA,int N,int length){
int i;
//i是新子序列的首元素
for(i=0;i<=N-2*length;i+=2*length){
Merge1(A,TmpA,i,i+length,i+2*length-1);
}
//最后是不是比一个length还多
//只要比一个length多1就是两个子列,可以归并
//第二个子列最后一个元素一定是A[N-1]
//不然的话只有一个子列只能贴在末尾(内部有序)
//等待最后一步使整个序列完全有序
if(i+length<N){
Merge1(A,TmpA,i,i+length,N-1);
}else{
for(int j=i;j<N;j++) TmpA[j]=A[j];
}
}
void Merge_Sort(int* A,int N){
int length=1;//初始化子序列长度
int* TmpA=new int[N];
if(TmpA){
while(length<N){
Merge_pass(A,TmpA,N,length);
length*=2;
Merge_pass(TmpA,A,N,length);
length*=2;
}
delete(TmpA);
}
else printf("空间不足\n");
}
七、快速排序

#include <iostream>
#define MAXN 100001
using namespace std;
//或者直接用库函数swap(int,int)也行
void swap1(int* a,int* b){
int t=*a;
*a=*b;
*b=t;
}
void Insertion_Sort(int* a,int N){
int j;
int tmp;
for(int i=1;i<N;i++){
tmp=a[i];
for(j=i-1;j>=0;j--){
if(a[j]>tmp) a[j+1]=a[j];
else break;
}
a[j+1]=tmp;
}
}
int Median3(int* a,int Left,int Right){
int center=(Left+Right)/2;
if(a[center]<a[Left]) swap1(&a[center],&a[Left]);
if(a[Left]>a[Right]) swap1(&a[Left],&a[Right]);
if(a[center]>a[Right]) swap1(&a[center],&a[Right]);
swap1(&a[Right-1],&a[center]);
return a[Right-1];
}
void QSort(int* a,int Left,int Right){
int Cutoff=200;
//Cutoff不能取1,算High会越界
if(Cutoff<=Right-Left){
int Pivot=Median3(a,Left,Right);
//Pivot主元的值
int Low=Left,High=Right-1;
while(1){
while(a[++Low]<Pivot) ;
while(a[--High]>Pivot);
if(Low<High) swap1(&a[Low],&a[High]);
else break;
}
//Low是正确的主元位置
swap1(&a[Low],&a[Right-1]);
QSort(a,Left,Low-1);
QSort(a,Low+1,Right);
}
else Insertion_Sort(a+Left,Right-Left+1);
}
void Quick_Sort(int* a,int N){
QSort(a,0,N-1);
}
#include<stdio.h>
#include<stdlib.h>
int a[1010];
int n;
void partition(int begin,int last){
if(begin>=last) return;
int key=a[begin];
int left=begin,right=last;
while(1){
while(a[right]>key){
if((right-1)>=begin) right--;
else break;
}
while(a[left]<=key){
if(left+1<=last) left++;
else break;
}
if(left<right){
int t=a[left];
a[left]=a[right];
a[right]=t;
}else break;
}
a[begin]=a[right];
a[right]=key;
for(int i=0;i<n;i++){
printf("%d ",a[i]);
}
printf("\n");
partition(begin,right-1);
partition(right+1,last);
}
int main(){
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
partition(0,n-1);
for(int i=0;i<n;i++){
printf("%d ",a[i]);
}
return 0;
}
八、基数排序
//版本1:只适用于0和正整数大小,没法比较负数
#include <iostream>
#define MAXN 100001
using namespace std;
#define MaxDigit 10//最大MaxDigit位数,最多MaxDigit个关键字
#define Radix 10 //进制基数,桶数量
struct node
{
int key;
node* next;
};
struct HeadNode{
node* head;
node* tail;
};
typedef HeadNode Bucket[Radix];//Radix个桶
int GetDigit(int x,int D){
//获取x第D次位上的数
int d;
for(int i=1;i<=D;i++){
d=x%Radix;
x/=Radix;
}
return d;
}
void Radix_LSD_Sort(int* a,int N){
Bucket B;
//初始化每个桶为空链表
for(int i=0;i<Radix;i++){
B[i].head=B[i].tail=NULL;
}
//将初始待排序列逆序存入初始链表List
node* List=NULL;
node* tmp;
for(int i=0;i<N;i++){
tmp=new node;
tmp->key=a[i];
tmp->next=List;
List=tmp;
}
//开始排序
int Di;
for(int D=1;D<=MaxDigit;D++){//对每个次位依次处理
node* p=List;
while(p){
//获得当前元素(p->key)的当前位(D)上数字
Di=GetDigit(p->key,D);
//从List中摘除,此时p为头结点,只需要指向下一个就行了
tmp=p;p=p->next;
tmp->next=NULL;
//插入B[Di]号桶尾
if(B[Di].head==NULL) B[Di].head=B[Di].tail=tmp;//当为空桶时
else{
B[Di].tail->next=tmp;
B[Di].tail=tmp;
}
}
//收集本轮排序结果过程
List=NULL;//重复利用List
for(int Di=Radix-1;Di>=0;Di--){
//如果桶不为空,整桶倒插进List
if(B[Di].head){
B[Di].tail->next=List;
List=B[Di].head;
B[Di].head=B[Di].tail=NULL;
}
}
}
//将最终排序结果List倒入a,并释放空间
for(int i=0;i<N;i++){
tmp=List;
List=List->next;
a[i]=tmp->key;
delete tmp;
}
}
//版本2:支持负数的基数排序
//利用偏移量,注意修改最大位数
//为了防止溢出,可能还需要修改key的类型
#include <iostream>
#define MAXN 100001
using namespace std;
#define keyType long long int
#define OFFSET 10000000000
#define MaxDigit 13//最大MaxDigit位数,最多MaxDigit个关键字
#define Radix 10 //进制基数,桶数量
struct node
{
keyType key;
node* next;
};
struct HeadNode{
node* head;
node* tail;
};
typedef HeadNode Bucket[Radix];//Radix个桶
int GetDigit(keyType x,int D){
//获取x第D次位上的数
int d;
for(int i=1;i<=D;i++){
d=x%Radix;
x/=Radix;
}
return d;
}
void Radix_LSD_Sort(int* a,int N){
Bucket B;
//初始化每个桶为空链表
for(int i=0;i<Radix;i++){
B[i].head=B[i].tail=NULL;
}
//将初始待排序列逆序存入初始链表List
node* List=NULL;
node* tmp;
for(int i=0;i<N;i++){
tmp=new node;
tmp->key=a[i]+OFFSET;
tmp->next=List;
List=tmp;
}
//开始排序
int Di;
for(int D=1;D<=MaxDigit;D++){//对每个次位依次处理
node* p=List;
while(p){
//获得当前元素(p->key)的当前位(D)上数字
Di=GetDigit(p->key,D);
//从List中摘除,此时p为头结点,只需要指向下一个就行了
tmp=p;p=p->next;
tmp->next=NULL;
//插入B[Di]号桶尾
if(B[Di].head==NULL) B[Di].head=B[Di].tail=tmp;//当为空桶时
else{
B[Di].tail->next=tmp;
B[Di].tail=tmp;
}
}
//收集本轮排序结果过程
List=NULL;//重复利用List
for(Di=Radix-1;Di>=0;Di--){
//如果桶不为空,整桶倒插进List
if(B[Di].head){
B[Di].tail->next=List;
List=B[Di].head;
B[Di].head=B[Di].tail=NULL;
}
}
}
//将最终排序结果List倒入a,并释放空间
for(int i=0;i<N;i++){
tmp=List;
List=List->next;
a[i]=tmp->key-OFFSET;
delete tmp;
}
}
int main(){
int N;
int a[MAXN];
scanf("%d",&N);
for(int i=0;i<N;i++){
scanf("%d",&a[i]);
}
Radix_LSD_Sort(a,N);
int flag=0;
for(int i=0;i<N;i++){
if(flag) printf(" %d",a[i]);
else{
printf("%d",a[i]);
flag=1;
}
}
system("pause");
return 0;
}
本文详细展示了冒泡排序、优化后的冒泡排序、插入排序、希尔排序、选择排序、堆排序、归并排序(递归与非递归两种方式)和快速排序的C++实现。这些排序算法在计算机科学中有着广泛的应用,理解并掌握它们对于提升编程技能至关重要。
3860

被折叠的 条评论
为什么被折叠?



