数据结构_排序 总结

一、排序的基本概念
排序算法的稳定性:
假定在待排序的记录集中,存在多个具有相同键值的记录,
若经过排序,这些记录的相对次序仍然保持不变,
即在原序列中,ki=kj且ri在rj之前,而在排序后的序列中,ri仍在rj之前,则称这种排序算法是稳定的;否则称为不稳定的。

二、插入排序
1、直接插入排序
基本思想:在插入第 i(i>1)个记录时,前面的 i-1个记录已经排好序。

void  insertSort (int  r[ ], int n){	
   for (i=2; i<=n; i++)   { 
       r[0]=r[i]; j=i-1;
       while (r[0]<r[j])       {  
           r[j+1]=r[j];	
	 j=j-1;	
        }
       r[j+1]=r[0];	
    }
}

2、希尔排序
基本思想:
将整个待排序记录分割成若干个子序列,
在子序列内分别进行直接插入排序,
待整个序列中的记录基本有序时,对全体记录进行直接插入排序。

void Shellsort(int r[],int n){
	for (i=d+1; i<=n; i++)  //将r[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、冒泡排序
基本思想:两两比较相邻记录的关键码,如果反序则交换,直到没有反序的记录为止。

void BubbleSort(int r[ ], int n)
{	
    exchange=n; 	
    while (exchange) 
    {
        bound=exchange; 
        exchange=0;  
        for (j=1; j<bound; j++)
            if (r[j]>r[j+1]) {
            	int temp=r[i];
                r[j]=r[j+1];
                r[j+1]=temp;
	      		exchange=j; 
            }
     }
 }

2、快速排序

  • 基本思想: 首先选一个轴值(即比较的基准), 通过一趟排序将待排序记录分割成独立的两部分, 前一部分记录的关键码均小于或等于轴值,
    后一部分记录的关键码均大于或等于轴值, 然后分别对这两部分重复上述方法,直到整个序列有序。
  • 选择轴值的方法:
    1.使用第一个记录的关键码;
    2.选取序列中间记录的关键码;
    3.比较序列中第一个记录、最后一个记录和中间记录的关键码,取关键码居中的作为轴值并调换到第一个记录的位置;
    4.随机选取轴值。
  • 选取不同轴值的后果: 决定两个子序列的长度,子序列的长度最好相等。
//实现一次划分
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为轴值记录的最终位置
}
//处理分割得到的两个待排序子序列
void QuickSort (int  r[ ], int first, int end )
{
    pivotpos = Partition (r, first, end );  //一次划分  
   //对前一个子序列进行快速排序
    QuickSort (r, first, pivotpos-1);      
   //对后一个子序列进行快速排序
   QuickSort (r, pivotpos+1, end ); 
}
//判别快速排序的结束
void QuickSort (int  r[ ], int first, int end )
{//在序列 first~end中递归地进行快速排序
    if (first < end) {					
          pivotpos = Partition (r, first, end );    
          QuickSort (r, first, pivotpos-1);
          QuickSort (r, pivotpos+1, end );
   }
}

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

void  selectSort ( int  r[ ], int n)
{   
    for ( i=1; i<n; i++) 
    {  
        index=i; 		
        for (j=i+1; j<=n; j++) 
           if  (r[j]<r[index])  index=j;
        if (index!=i)   r[i]<==>r[index]; 	 
    }
} 

2、堆排序
基本思想:
首先将待排序的记录序列构造成一个堆(大顶堆),
此时,选出了堆中所有记录的最大者,然后将它从堆中移走,
将剩余的记录再调整成堆,
这样又找出了次大的记录,以此类推,直到堆中只有一个记录。

void sift ( int r[ ], int k, int m )
{//要筛选结点的编号为k,堆中最后一个结点的编号为m 
    i=k;  j=2*i;  temp=r[i];  //将筛选记录暂存
    while (j<=m )           //筛选还没有进行到叶子
    {
        if (j<m && r[j]<r[j+1]) j++;  //左右孩子中取较大者
        if (temp>r[j]) break; 
        else {
             r[i]=r[j];   i=j;   j=2*i;
        }
     }
     r[i]=temp;   //将筛选记录移到正确位置
}
void  HeapSort ( int  r[], int n)
{
    for (i=n/2; i>=1; i--)      //初建堆
       sift(r, i, n) ;     
    for (i=1; i<n; i++ )
    {
       r[1]←→r[n-i+1];        //移走堆顶
       sift(r, 1, n-i);               //重建堆
    }
}

五、归并排序
归并:将两个或两个以上的有序序列合并成一个有序序列的过程。
归并排序的主要操作是归并,其主要思想是:将若干有序序列逐步归并,最终得到一个有序序列。

void Merge (int r[ ], int r1[ ], int s, int m, int t )
{
    i=s;   j=m+1;   k=s;
    while (i<=m && j<=t)
    {   
        if (r[i]<=r[j])  r1[k++]=r[i++];
        else  r1[k++]=r[j++]; 
     }
     if (i<=m)  while (i<=m)              //收尾处理
                           r1[k++]=r[i++];    //前一个子序列
     else  while (j<=t)
                  r1[k++]=r[j++];             //后一个子序列
} 
//一趟归并排序算法
void  MergePass (int  r[ ], int  r1[ ], int  n, int  h)
{
     i=1;		//第一个子序列的第一个元素
     while (i≤n-2h+1)                //情况1
     {
           Merge (r, r1, i, i+h-1, i+2*h-1);
           i+=2*h;
      }
      if (i<n-h+1) Merge (r, r1, i, i+h-1, n);   //情况2
      else for (k=i; k<=n; k++)    //情况3
                 r1[k]=r[k];
}
void msort(int a[], int r[], int s, int t){
    if(s==t) 
         return;              //如果只有一个数字则返回,无须排序
    int mid=(s+t)/2;
    msort(s,mid);                //分解左序列
    msort(mid+1,t);            //分解右序列
    int i=s, j=mid+1, k=s;   //接下来合并
    while(i<=mid && j<=t)  {
          if(a[i]<=a[j]) {
                r[k]=a[i];     k++; i++;
           }
          else {
               r[k]=a[j];  k++; j++;
          }
    }  
      while(i<=mid) {     //复制左边子序列剩余
           r[k]=a[i]; k++; i++;
       }
       while(j<=t)  {  //复制右边子序列剩余  
        
            r[k]=a[j]; k++; j++;
        }
        for(int i=s; i<=t; i++)
              a[i]=r[i];  
        return 0;
} 

六、分配排序
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、链式基数排序

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值