C++排序技术

一,排序的基本概念

1,稳定性的概念:同一数据重复出现,相对位置不发生变化则称稳定。

2,时间性能取决于比较次数+移动次数。

3,各类算法存储结构,顺序存储数组下标从1开始,0下标做辅助空间。

二,插入类的排序

1,直接插入排序,稳定

在插第i个记录时前i-1个已排好序

for (i=2; i<=n; i++) {
r[0]=r[i]; j=i-1;
while (r[0]<r[j]) { //r[0]做监视哨
r[j+1]=r[j];
j=j-1;
}
r[j+1]=r[0];
}
2,希尔排序(缩小增量排序),不稳定

将整个待排序记录分割成若干个子序列,在子序列内分别进行直接插入排序,待整个序列中的记录基本有序时,对全体记录进行直接插入排序。初始增量d=n/2(d个子序列同步进行)

for (d=n/2; d>=1; d=d/2){
for (i=d+1; i<=n; i++) {
r[0]=r[i];
j=i-d;
while (j>0 && r[0]<r[j])
{
r[j+d]=r[j]; //记录后移d个位置
j=j-d; //比较统一子序列的前一个记录
}
r[j+d]=r[0];
}
}
三,交换排序

1,相邻比序(冒泡),稳定

改进原版冒泡提高性能,减少比较次数,记录最后一次交换位置,下次交换到此结束,无交换时退出。

exchange=n;
while (exchange)
{
bound=exchange;
exchange=0;
for (j=1; j<bound; j++)
if (r[j]>r[j+1]) {
r[j]←→r[j+1];
exchange=j; //记录最后交换的位置
}
}
2,快速排序

首先选一个轴值(即比较的基准),通过一趟排序将待排序记录分割成独立的两部分,前一部分记录的关键码均小于或等于轴值,后一部分记录的关键码均大于或等于轴值,然后分别对这两部分重复上述方法,直到整个序列有序。可用二叉树描述,深度表示递归次数。

void QuickSort (int r[ ], int first, int end )
{
if (first < end) {
pivotpos = Partition (r, first, end ); //一次划分
//对前一个子序列进行快速排序
QuickSort (r, first, pivotpos-1);
//对后一个子序列进行快速排序
QuickSort (r, pivotpos+1, end );
}
}
int Partition(int r[ ], int first, int end)
{
i=first; j=end; //初始化
r[0]=r[i];
while (i<j)
{
while (i<j && r[0]<= r[j]) j–; //右侧扫描
if (i<j) {
r[i]=r[j]; i++; //将较小记录交换到前面
}
while (i<j && r[i]<= r[0]) i++; //左侧扫描
if (i<j) {
r[j]=r[i]; j–; //将较大记录交换到后面
}
}
r[i]=r[0];
retutn i; //i为轴值记录的最终位置
}
四,选择排序,无最好最坏情况之分。

1,简单选择排序,不稳定,时间复杂度永远是n方

基本思想:第i 趟在n-i+1(i=1,2,…,n-1)个记录中选取关键码最小的记录作为有序序列中的第i个记录。

for ( i=1; i<n; i++) 
{  
    index=i; 		//index记录有序数组的最后位置
    for (j=i+1; j<=n; j++) 
       if  (r[j]<r[index])  index=j;
    if (index!=i)   r[i]<==>r[index]; 	 
}

2,堆排序,不稳定

堆是具有下列性质的完全二叉树:每个结点的值都小于或等于其左右孩子结点的值(称为小根堆),或每个结点的值都大于或等于其左右孩子结点的值(称为大根堆)。

要得到升序的序列则要构造大根堆

#include<bits/stdc++.h>
using namespace std;
int judge(int a[],int i,int j)
{
int k=i;
int l=2k;
int t=a[k];
while(l<=j)
{
if(l<j&&a[l]<a[l+1])
l++;
if(t>a[l]) break;
else
{
a[k]=a[l];
k=l;
l=2
k;
}
}
a[k]=t;
}
void h(int a[],int n){
for(int j=n/2;j>=1;j–)
judge(a,j,n);
for(int i=1;i<n;i++)
{
//swap(a[1],a[n-i+1]);
int f=a[1];
a[1]=a[n-i+1];
a[n-i+1]=f;
judge(a,1,n-i);
}
}
int main()
{
int n,a[9999];
cin>>n;

for(int i=1;i<=n;i++)
cin>>a[i];
h(a,n);

 for(int i=1;i<=n;i++)
cout<<a[i]<<" ";
}

五,归并排序(分治的思想)

将n个待排序的记录的序列看成n个长度为一的有序序列。

1,二路归并排序

归并排序的主要操作是归并,其主要思想是:将若干有序序列逐步归并,最终得到一个有序序列。 无法原地进行引入相同大小的数组存中间结果

#include<bits/stdc++.h>
using namespace std;
void judge(int a[],int b[],int s,int m,int t)
{
int i=s;
int j=m+1;
int k=s;
while(i<=m&&j<=t)
{
if(a[i]<=a[j]) b[k++]=a[i++];
else
b[k++]=a[j++];
}
if(i<=m)
while(i<=m)
{
b[k++]=a[i++];
}
else
while(j<=t)
b[k++]=a[j++];
}
void mp(int a[],int b[],int n,int h)
{
int i=1;
while(i<=n-2h+1)
{
judge(a,b,i,i+h-1,i+2
h-1);
i+=2h;
}
if(i<n-h+1) judge(a,b,i,i+h-1,n);
else for(int k=i; k<=n; k++)
b[k]=a[k];
}
void msort(int a[],int b[],int n)
{
int h=1;
while(h<n)
{
mp(a,b,n,h);
h=2
h;
mp(b,a,n,h);
h=2*h;
}
}
int main()
{
int n,a[9999],b[9999];
cin>>n;

for(int i=1; i<=n; i++)
    cin>>a[i];
    msort(a,b,n);
for(int i=1; i<=n; i++)
    cout<<a[i]<<" ";
cout<<endl;
for(int i=1; i<=n; i++)
    cout<<b[i]<<" ";

}

六,分配排序

基于分配和收集,不经过比较

1,桶式排序,稳定

int main(){
Node *s,*first; head *list;
int m;cin>>m;
list=new head[m];
for (int i=0;i<=m;i++){
list[i].first=NULL; list[i].rear=NULL;}
int n;
cin>>n;
first=NULL;
for( i=0;i<n;i++)
{ s=new Node; cin>>s->data; s->next=first; first=s; }
distribute(first,n,list);
collect(list,first,m);
Node *p=first;
while§{
cout<data<<"\t"; p=p->next; }
cout<<endl;
return 0;
}
2,基数排序,稳定

低位优先,尾插法

void distribute(Node *first, int n, head *list,int d){
Node *p,*q; p=first; int data, s,t;
while§ {
data=p->data;
s=pow(10,d);t=s/10;data=data%s;data=data/t;
q=p->next;
if( list[data].first)
{list[data].rear->next=p; list[data].rear=p;}
else
list[data].first=list[data].rear=p;
list[data].rear->next=NULL;
p=q;
}

}
void collect( head *list, Node *&first,int m){
int i=0,j;
while(list[i].firstNULL) i++;
if(i>m) return;
first=list[i].first;
while(i<=m) {
j=i+1;
while(list[j].first
NULL) j++;
if(j>m) return;
list[i].rear->next=list[j].first;
i=j;
}
}

cin>>d;
for(i=1;i<=d;i++) //处理每一“位”(个位、十位…)
{
distribute(first,n,list ,i);
collect(list,first,m);
for (int i=0;i<=m;i++)
{
list[i].first=NULL;
list[i].rear=NULL;
}
}

发布了18 篇原创文章 · 获赞 0 · 访问量 202

猜你喜欢

转载自blog.csdn.net/mushuige/article/details/103795891
今日推荐