排序算法

排序

1. 直接插入排序

原理:将当前无序区a[i...n-1]的记录一个一个插入到有序区a[0....i-1]合适位置;

 

 1 void insert_sort(int a[], int n)
 2 {
 3     int j;
 4     for(int i=1;i<n;i++)
 5     {
 6         int temp=a[i];
 7         
 8         for(j=i-1;j>=0&&temp<a[j];j--)
 9         {
10             a[j+1]=a[j];
11         }
12         a[j+1]=temp;
13     }
14 }

2. shell 排序

原理:实质为分组插入排序,首先按增量为d分成若干组,下标相差d的元素放在一组使用直接插入排序;然后用一个较小的增量继续分组和排序,直至增量减到1,整个分组即为一组,排序完成。

 1 void shell_sort(int *a, int n)
 2 {
 3     for(int h=n/2;h>0;h=h/2)
 4     {
 5          for(int i=h;i<n;i++)                     //for 循环就是增量为h的直接插入排序
 6          {
 7              int temp=a[i];
 8              int j;
 9              for(j=i-h;j>=0&&temp<a[j];j=j-h)
10              {
11                  a[j+h]=a[j];
12              }
13              a[j+h]=temp;
14          }
15     }
16 }

3. 冒泡排序

原理:首先将a[0...n-1] 垂直排列,根据气泡原理,较轻的会浮在较重的上面。 自底向上扫描:凡扫描到违反此原则的轻气泡,就使其上浮。

每遍扫描都会是最轻的一个元素上浮。扫描n-1 趟

 1 void bubble_sort(int a[],int n)
 2 {
 3     for(int i=0;i<n-1;i++)
 4     {
 5         for(int j=n-1;j>i;j--)
 6         {
 7             if(a[j]<a[j-1])
 8             {
 9                 int temp=a[j];
10                 a[j]=a[j-1];
11                 a[j-1]=temp;
12             }
13         }
14     }
15 }

 4. 快速排序

快速排序是一种交换排序,采用的了“分治”的策略。

分治法的哦基本思想是: 将原问题分解为若干个规模更小但结构和原问题相似的子问题,递归解决这些子问题,然后将这些子问题的解组合为原问题的解。

快速排序基本思想:将当前无序区A[low...high],采用分治法描述为:

(1)分解:在A[low...high]中选用一个元素作为基准(pivot),以此基准将A[low...high]划分为两个左右区间A[low...pivot-1],A[pivot+1...high]。使得左区间都小于A[pivot],右区间都大于A[pivot]。即A[low...pivot-1]<=A[pivot]<=A[pivot+1...high]。

(2)求解:递归对左右区间进行快速排序。

(3)组合:递归做完,其区间即为有序。

 1 void quick_sort(int a[],int low, int high)
 2 {
 3     int i,j,pivot;
 4     if(low<high)
 5     {
 6         pivot=a[low];
 7         i=low;
 8         j=high;
 9         while(i<j)                          //终止的条件极为i=j
10         {
11             while(i<j&&a[j]>=pivot)
12                 j--;
13             if(i<j)
14                 a[i++]=a[j];                 //将比pivot小的元素移到低端
15 
16             while(i<j&&a[i]<=pivot)
17                 i++;
18             if(i<j)
19                 a[j--]=a[i];               //将比pivot 大的元素移到高端
20         }
21         a[i]=pivot;
22         quick_sort(a,low,i-1);
23         quick_sort(a,i+1,high);
24     }
25 }

 

 5. 直接选择排序

基本思想:有序区A[0...i-1]和无序区A[i...n-1]。在无序区A[i....n-1]中选择一个最小的元素与A[i]进行交换,有序区增加1 为A[0....i]。

 1 void select_sort(int a[], int n)
 2 {
 3     int i,j,l,min;
 4     for(i=0;i<n-1;i++)    //遍历n-1遍
 5     {
 6         int min=a[i];
 7         int l=i;
 8         for(j=i;j<n;j++)
 9         {            
10             if(a[j]<min)
11             {
12                 min=a[j];
13                 l=j;
14             }
15         }
16         a[l]=a[i];
17         a[i]=min;
18     }
19 }

 6. 堆排序

堆排序是利用的堆的特性进行排序的一种排序方法。

堆是一个完全二叉树,分为大根堆和小根堆。

 

在数组的非降序排序中,需要使用的就是大根堆,因为根据大根堆的要求可知,最大的值一定在堆顶。

既然是堆排序,首先就要建堆,而建堆的核心是调堆,使满足堆的特性。调堆首先从最后一个非叶子节点开始,假设有数组A = {1, 3, 4, 5, 7, 2, 6, 8, 0}。那么调堆的过程如下图,数组下标从0开始,A[3] = 5开始。分别与左孩子和右孩子比较大小,如果A[3]最大,则不用调整,否则和孩子中的值最大的一个交换位置,在图1中是A[7] > A[3] > A[8],所以A[3]与A[7]对换,从图1.1转到图1.2。

 

 

 1 int heapSize=0; //堆大小
 2 int leftChild(int index)
 3 {
 4     return (index<<1)+1; //下标从0开始
 5 }
 6 int rightChild(int index)
 7 {
 8     return (index<<1)+2;
 9 }
10 void maxHeapify(int a[],int index)  //调整堆,index 表示堆顶索引
11 {
12     int largest=index;            //最大索引
13     int left=leftChild(index);    //左子节点索引
14     int right=rightChild(index);   //右子节点索引
15     if(left<heapSize&&a[left]>a[largest])
16         largest=left;
17     if(right<heapSize&&a[right]>a[largest])
18         largest=right;
19 
20     if(largest!=index)
21     {
22         swap(a[index],a[largest]);
23         maxHeapify(a,largest);    //新父节点,递归调整堆
24     }
25 }
26 void buildMaxHeap(int a[], int length)
27 {
28     heapSize=length;
29     int begin=length/2-1;
30     for(int i=begin;i>=0;i--)
31     {
32         maxHeapify(a,i);
33     }
34 
35 }
36 
37 void heap_sort(int a[],int length)
38 {
39     int i;
40     buildMaxHeap(a,length);
41     for(i=length-1;i>=1;i--)
42     {
43         swap(a[0],a[i]); //堆顶a[0]为最大元素,被换至数组尾部a[i]
44         heapSize--;       //从堆中移除该元素
45         maxHeapify(a,0);  //重建堆
46     }
47 }

 7. 归并排序

自顶向下解法:

(1)分解:将当前区间一分为二,求分裂点;

(2)求解:递归对两个子区间A[low...middle]和A[middle+1, high]进行归并排序;

(3)组合:将以排好序的两个子区间进行合并为一个有序的区间A[low...high];

(4)递归的终止条件,字区间长度为1;

 1 /***********归并排序************************/
 2 void merge(int a[],int tmp[],int lPos,int rPos,int rEnd)
 3 {
 4     int lEnd=rPos-1;
 5     int tmpPos=lPos;
 6     int elemNum=rEnd-lPos+1;
 7     while(lPos<=lEnd&&rPos<=rEnd)
 8     {
 9         if(a[lPos]<a[rPos])
10             tmp[tmpPos++]=a[lPos++];
11         else
12             tmp[tmpPos++]=a[rPos++];
13     }
14     while(lPos<=lEnd)
15         tmp[tmpPos++]=a[lPos++];
16     while(rPos<=rEnd)
17         tmp[tmpPos++]=a[rPos++];
18     for(int i=0;i<elemNum;i++,rEnd--)
19     {
20         a[rEnd]=tmp[rEnd];
21     }
22 }
23 void msort(int a[],int tmp[],int low,int high)
24 {
25     if(low<high)
26     {
27         int middle=(low+high)/2;
28         msort(a,tmp,low,middle);
29         msort(a,tmp,middle+1,high);
30         merge(a,tmp,low,middle+1,high);
31 
32     }
33 }
34 void merge_sort(int a[], int len)
35 {
36     int *tmp;
37     tmp=new int[len];
38     if(tmp!=NULL)
39     {
40         msort(a,tmp,0,len-1);
41         delete []tmp;
42     }
43 }

 

8. 基数排序

基数排序是桶排序的延伸和改进。

于两种不同的排序顺序,我们将基数排序分为LSD(Least significant digital)或MSD(Most significant digital),

LSD的排序方式由数值的最右边(低位)开始,而MSD则相反,由数值的最左边(高位)开始。

LSD算法如下:

 1 /******************基数排序********************/
 2 int get_kthDigit(double number,int k)   //获取第k 位的数值
 3 {
 4     number/=(int)pow(10.0,k);
 5     int res=(int)number%10;
 6     return res;
 7 }
 8 int get_max(int a[],int len) //最大值
 9 {
10     int max=a[0];
11     for(int i=1;i<len;i++)
12     {
13         if(max<a[i])
14             max=a[i];
15     }
16     return max;
17 }
18 int get_digitNumber(int number) //计算位数
19 {
20     int digit=0;
21     while(number)
22     {
23         number/=10;
24         digit++;
25     }
26     return digit;
27 }
28 void radix_sort(int a[],int len)
29 {
30     int count[10]={0};
31     int *temp[10];
32     for(int i=0;i<10;i++)
33     {
34         temp[i]=new int[len];
35         memset(temp[i],0,sizeof(int)*len);
36     }
37     int max=get_max(a,len);
38     int maxDigit=get_digitNumber(max);
39     for(int i=0;i<maxDigit;i++)
40     {
41         memset(count,0,sizeof(int)*10);
42         for(int j=0;j<len;j++)
43         {
44             int x=get_kthDigit(a[j],i);
45             temp[x][count[x]]=a[j];
46             count[x]++;
47         }
48         int index=0;
49         for(int j=0;j<10;j++)
50         {
51             for(int k=0;k<count[j];k++)
52                 a[index++]=temp[j][k];
53         }
54     }
55 }

 

转载于:https://www.cnblogs.com/kennethshu/p/4182016.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值