插入类排序

直接插入排序 
1.定义

    直接插入排序( straight insertion sort )是一种最简单的排序方法。它的基本操作是将一个记录插入到一个长度为 m (假设)的有序表中,使之仍保持有序,从而得到一个新的长度为 m + 1 的有序表。
2.算法思路
  设有一组关键字{ K 1 , K 2 ,…, K n };排序开始就认为 K 1 是一个有序序列;让 K 2 插入上述表长为 1 的有序序列,使之成为一个表长为 2 的有序序列;然后让 K 3 插入上述表长为 2 的有序序列,使之成为一个表长为 3 的有序序列;依次类推,最后让 K n 插入上述表长为 n-1 的有序序列,得一个表长为 n 的有序序列。
【例】设有一组关键字序列{ 55 , 22 , 44 , 11 , 33 },这里 n=5 ,即有 5 个记录。请将其按由小到大的顺序排序。排序过程如图9.1所示。
      
具体算法演示请点击查看算法演示
3.具体算法
void insertSort(int a[],int count)   /*count为排序数字个数*/
{
   int i,j,temp;
   for(i=1;i<count;i++)    /*依次比较前面排好序的元素和temp的大小,若temp大则前面排好序的依次后移*/
   {
      temp=a[i];
      j=i-1;
      while(a[j]>temp && j>=0)
      {
        a[j+1]=a[j];
         j--;
      }
      if(j!=(i-1)) /*定好temp的最终位置*/       
      {
        a[j+1]=temp;
      }
         
   }
}


4.算法时间复杂度 
  此算法外循环 n-1 次,在一般情况下内循环平均比较次数的数量级为O(n) ,所以算法总时间复杂度为O(n 2) 。
5.直接插入排序的稳定性

  直接插入排序是稳定的排序方法



折半插入排序 
1.定义

    当直接插入排序进行到某一趟时,对于 r[i].key 来讲,前边 i-1 个记录已经按关键字有序。此时不用直接插入排序的方法,而改为折半查找,找出 r[i].key 应插的位置,然后插入。这种方法就是折半插入排序( Binary insertion sort )。
2.具体算法
template<class T>
void binasort(T r[],int n)

int i,j,l,h,mid;

      for (i=2;i<=n;i++)
      {

 r[0]=r[i];

             l=1;

             h=i-1;           //认为在r[1]和r[i-1]之间已经有序

       while(l<=h)          //对有序表进行折半查找

       { 

mid=(l+h)/2;

                 if(a[0].key<a[mid].key)

h=mid-1;

      else 

l=mid+1;

       }        //结果在1位置

 for(j=i-1;j>=1;j--)a[j+1]=a[j];

        a[1]=a[0];

        }
  }  //binasort
3.折半插入排序的时间复杂度
  折半插入排序,关键字的比较次数由于采用了折半查找而减少,数量级为O (nlog 2 n) ,但是元素移动次数仍为O (n 2 ) 。故折半插入排序时间复杂度仍为O (n 2 ) 。折半插入排序方法是稳定的。 





希尔排序 
1.定义

    希尔排序( shell sort )是 D .L.希尔( D.L.Shell )提出的“缩小增量”的排序方法。它的作法不是每次一个元素挨一个元素的比较。而是初期选用大跨步(增量较大)间隔比较,使记录跳跃式接近它的排序位置;然后增量缩小;最后增量为 1 ,这样记录移动次数大大减少,提高了排序效率。希尔排序对增量序列的选择没有严格规定。
2.算法思路
  ①先取一个正整数 d1(d 1 <;n) ,把全部记录分成 d1个组,所有距离为 d1的倍数的记录看成一组,然后在各组内进行插入排序;
  ②然后取 d2( d2 < d1 ) 。
  ③重复上述分组和排序操作;直到取 di=1(i>=1) ,即所有记录成为一个组为止。一般选 d1约为 n/2 , d2为 d 1 /2 , d3为 d 2 /2 ,…, d i =1 。

  【例】有一组关键字{ 76 , 81 , 60 , 22 , 98 , 33 , 12 , 79 },将其按由小到大的顺序排序。这里 n=8 ,取 d 1 =4 , d 2 =2 , d 3 =1 。排序过程如图9.2所示。



3.具体算法



#include<iostream>  
using namespace std;  
   
void shell(int *work,int n)  
{  
int i,j,x,d;  
d= n / 2;  
while (d>=1)  
{  
  for (i=d+1;i<=n;i++)  
  {  
    x=work[i];  
    j=i-d;  
    while ((j>0) && (x<work[j]))  
    {  
    work[j+d]=work[j];  
    j-=d;  
    }  
    work[j+d]=x;  
  }  
  d /= 2;  
}  
}  
int main(){  
    int a[100],b,c,n,i;  
    cout<<"请输入需排序的数字个数:";  
    cin>>n;  
    cout<<"请输入需排序的数字";  
    for (i=1;i<=n;i++)  
    {  
        cin>>a[i];  
    }  
    shell(a,n);    
    cout<<"从小到大排序结果为:";  
    for (i=1;i<=n;i++)  
    {  
        cout<<a[i]<<' ';  
    }  
    system("pause");  
} 


4.算法分析
  当K=1时,此算法就等同于直接插入排序方法。由于前边大增量的处理,使关键字大体有序,因此最后一趟排序移动的记录少,处理速度快。
  有人在大量实验基础上推出,它的时间复杂长为 O(n 1.3 ) 。如果对关键字序列 {6,7,5 1 ,2,5 2 ,8} 进行希尔排序,可以看出希尔排序是不稳定的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值