数据结构总结(排序技术)

  数据结构也到达了终点,最后的考试也步步紧逼。最后的时间里,有必要合理分配空闲时间,制定好学习计划,在考前充分复习,尽自己最大努力。这最后一章,介绍了与查找技术不同的排序技术,但同样的都是一些优秀的思想方法,思维上有些难度,不去深入理解,很容易出现细节方面问题。

一,排序的基本概念

  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+1i=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=2*k;
    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-2*h+1)
    {
        judge(a,b,i,i+h-1,i+2*h-1);
        i+=2*h;
    }
    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(p){
		cout<<p->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(p)	{
		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].first==NULL) 	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;	
		}
	}

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章