c语言排序.docx
《c语言排序.docx》由会员分享,可在线阅读,更多相关《c语言排序.docx(14页珍藏版)》请在冰豆网上搜索。
c语言排序
快速排序--C语言
2007-03-1423:
42 1714人阅读 评论(0) 收藏 举报
快速排序是对冒泡排序的一种改进。
它的基本思想是:
通过一躺排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一不部分的所有数据都要小,然后再按次方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
假设要排序的数组是A[1]……A[N],首先任意选取一个数据(通常选用第一个数据)作为关键数据,然后将所有比它的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一躺快速排序。
一躺快速排序的算法是:
1)、设置两个变量I、J,排序开始的时候I:
=1,J:
=N;
2)以第一个数组元素作为关键数据,赋值给X,即X:
=A[1];
3)、从J开始向前搜索,即由后开始向前搜索(J:
=J-1),找到第一个小于X的值,两者交换;
4)、从I开始向后搜索,即由前开始向后搜索(I:
=I+1),找到第一个大于X的值,两者交换;
5)、重复第3、4步,直到I=J;
例如:
待排序的数组A的值分别是:
(初始关键数据X:
=49)
A[1] A[2] A[3] A[4] A[5] A[6] A[7]:
49 38 65 97 76 13 27
进行第一次交换后:
27 38 65 97 76 13 49
(按照算法的第三步从后面开始找
进行第二次交换后:
27 38 49 97 76 13 65
(按照算法的第四步从前面开始找>X的值,65>49,两者交换,此时I:
=3)
进行第三次交换后:
27 38 13 97 76 49 65
(按照算法的第五步将又一次执行算法的第三步从后开始找
进行第四次交换后:
27 38 13 49 76 97 65
(按照算法的第四步从前面开始找大于X的值,97>49,两者交换,此时J:
=4)
此时再执行第三不的时候就发现I=J,从而结束一躺快速排序,那么经过一躺快速排序之后的结果是:
27 38 13 49 76 97 65,即所以大于49的数全部在49的后面,所以小于49的数全部在49的前面。
快速排序就是递归调用此过程——在以49为中点分割这个数据序列,分别对前面一部分和后面一部分进行类似的快速排序,从而完成全部数据序列的快速排序,最后把此数据序列变成一个有序的序列,根据这种思想对于上述数组A的快速排序的全过程如图6所示:
初始状态 {49 38 65 97 76 13 27}
进行一次快速排序之后划分为 {27 38 13} 49 {76 97 65}
分别对前后两部分进行快速排序{13} 27 {38}
结束 结束 49 {65} 76 {97}
图6 快速排序全过程
// QuickSort.cpp :
Defines the entry point for the console application.
//
#include "stdafx.h"
#include"stdio.h"
void main()
{
void quickSort(int [],int,int);
int a[7]={8,2,6,12,1,9,5};
int i;
quickSort(a,0,6);/*排好序的结果*/
for(i=0;i<7;i++)
printf("%4d",a[i]);
}
void quickSort(int a[],int left,int right)
{
int i,j,temp;
i=left;
j=right;
temp=a[left];
if(left>right)
return;
while(i!
=j)/*找到最终位置*/
{
while(a[j]>=temp && j>i)
j--;
if(j>i)
a[i++]=a[j];
while(a[i]<=temp && j>i)
i++;
if(j>i)
a[j--]=a[i];
}
a[i]=temp;
quickSort(a,left,i-1);/*递归左边*/
quickSort(a,i+1,right);/*递归右边*/
}
希尔(Shell)排序——改良的插入排序算法
分类:
算法 JAVA语言2011-10-1419:
27 99人阅读 评论(0) 收藏 举报
希尔排序是插入排序中的一种,前面一篇文章(点击查看)中提到的插入排序算法准确的来说应该称为“直接插入排序算法”,而这里介绍的希尔排序算法是对直接插入排序算法改进之后形成的一种算法,该算法是由D.LShell于1959年提出的,它也因此而得名,又称缩小增量排序算法。
基本思想
设初始序列有n个元素,选定一个小于n大于或等于1的整数gap作为间隔,将全部元素分成gap个子序列,所有距离为gap的元素放在同一个子序列中,在每个子序列中分别采用直接插入算法进行排序;然后缩小间隔gap,如令gap=gap/2,重复上面的子序列划分和子序列排序动作;直到最后去gap=1,将所有的元素放到一个序列中为止。
简单示例
初始序列:
21254925168
第一步:
第二步:
第三步:
算法说明
开始时gap的值较大,子序列中的元素较少,排序速度比较快;随着排序进展,gap的值逐渐减小,子序列中的元素增多,不过由于前面排序工作的基础,大多数元素已基本有序,所以排序速度依然是比较快的。
对于gap值的取法有很多种。
最初Shell提出取gap=n/2,gap=gap/2,直到gap=1。
后来Knuth提出取gap=gap/3+1,另外还有人认为gap都去奇数比较好,也有人说让各个gap值互质为好。
另外,由上面的实例可以看出:
该算法是不稳定的算法。
算法分析
对特定的待排序序列,可以准确的估算元素的比较次数和移动次数;但是,想要弄清楚元素比较次数和移动次数与增量选择之间的依赖关系,并给出完整的数学分析,还没有人能够做到。
另外,由上面的实例可以看出:
该算法是不稳定的算法。
算法实现
C语言:
[cpp] viewplaincopyprint?
1.#include
2.#include
3.#include
4.#define MAX 10
5.#define SWAP(x,y) {int t; t = x; x = y; y = t;}
6.
7.void shellsort(int[]);
8.
9.int main(void) {
10. int number[MAX] = {0};
11. int i;
12.
13. srand(time(NULL));
14.
15. printf("排序前:
");
16. for(i = 0; i < MAX; i++) {
17. number[i] = rand() % 100;
18. printf("%d ", number[i]);
19. }
20.
21. shellsort(number);
22.
23. return 0;
24.}
25.
26.void shellsort(int number[]) {
27. int i, j, k, gap, t;
28.
29. gap = MAX / 2;
30.
31. while(gap > 0) {
32. for(k = 0; k < gap; k++) {
33. for(i = k+gap; i < MAX; i+=gap) {
34. for(j = i - gap; j >= k; j-=gap) {
35. if(number[j] > number[j+gap]) {
36. SWAP(number[j], number[j+gap]);
37. }
38. else
39. break;
40. }
41. }
42. }
43.
44. printf("\ngap = %d:
", gap);
45. for(i = 0; i < MAX; i++)
46. printf("%d ", number[i]);
47. printf("\n");
48.
49. gap /= 2;
50. }
51.}
JAVA语言:
[java] viewplaincopyprint?
1.public class ShellSort {
2. public static void sort(int[] number) {
3. int gap = number.length / 2;
4.
5. while(gap > 0) {
6. for(int k = 0; k < gap; k++) {
7. for(int i = k+gap; i < number.length; i+=gap) {
8. for(int j = i - gap; j >= k; j-=gap) {
9. if(number[j] > number[j+gap]) {
10. swap(number, j, j+gap);
11. }
12. else
13. break;
14. }
15. }
16. }
17.
18. gap /= 2;
19. }
20. }
21.
22. private static void swap(int[] number, int i, int j) {
23. int t;
24. t = number[i];
25. number[i] = number[j];
26. number[j] = t;
27. }
28.}
归并排序详解 2012-3-1708:
49 阅读(12)
下一篇:
谷歌算法揭秘:
一... | 返回日志列表
∙赞
∙转载
∙分享
∙评论
∙复制地址
∙更多
//划分待排序数据为左右两部分,比较左右两部分。
存入临时数组
//将排序好的数据在临时数组中copy到原数组中
//
#include
#include
#defineMAX10
void
print_array(int*array_test,unsignedintx)
{
unsignedinti;
for(i=0;i {
printf("%d",array_test[i]);
}
printf("\n");
}
staticvoid
merge(intarray[],intlow,intmid,inthigh)
{
inti,k;
int*temp=(int*)malloc((high-low+1)*sizeof(int));//申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
intbegin1=low;//左半边开始下标
intend1=mid; //左半边结束下标
intbegin2=mid+1; //右半边开始下标
intend2=high; //右半边开始下标
printf("mid=%d",mid);
//由于begin1end1 begin2 end2中都有需要比较的元素,故需要<=
for(k=0;begin1<=end1&&begin2<=end2;k++)//比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
{
if(array[begin1] {
temp[k]=array[begin1++];
}
else
{
temp[k]=array[begin2++];
}
}
//由于begin1end1 begin2 end2中都有需要比较的元素,故需要<=
while(begin1<=end1)//若第一个序列有剩余,直接拷贝出来粘到合并序列尾
{
temp[k++]=array[begin1++];
}
while(begin2<=end2)//若第二个序列有剩余,直接拷贝出来粘到合并序列尾
{
temp[k++]=array[begin2++];
}
for(i=0;i<(high-low+1);i++)//将排序好的序列拷贝回数组中
{
array[low+i]=temp[i];
}
printf("合并:
");
print_array(array,MAX);
free(temp);
}
void
merge_sort(intarray[],unsignedintfirst,unsignedintlast)
{
intmid=0;
if(first {
mid=(first+last)/2;
merge_sort(array,first,mid);//划分左半部分
merge_sort(array,mid+1,last);//划分右半部分
merge(array,first,mid,last);//合并
}
}
intmain(void)
{
int array_test[MAX]={0,9,8,7,6,5,4,3,2,1};
printf("start:
");
print_array(array_test,MAX);
merge_sort(array_test,0,MAX-1);
printf("end:
");
print_array(array_test,MAX);
return0;
}
一、插入排序算法
算法思想:
对于一个有N个记录的待排序的序列,整个排序过程为进行N-1趟插入。
先将表中的第一个记录看成一个有序的子序列,然后从第二个记录起逐个查找合适的位置进行插入,以此类推,此排序过程就是将数组分为无序区和有序区两个区,然后不断将无序区的第一个元素按大小顺序插入到有序区中去,最终将所有无序区元素都移动到有序区完成排序。
一个比较直观的比喻就是像我们平时玩扑克牌,在你手里的牌是你经过排序的,是一个有序的序列,之后从桌子上每抓一张牌,你都会将它插入到合适的位置用来保证牌得有序性,知道所有的牌抓完为止。
示意图解析:
示意图中绿色的区域代表有序区,白色的部分是无序区,插入排序算法的过程就是将无序区的第一个元素插入到有序区合适的位置,知道整个数组均为有序区。
C++源码:
1.void InsertSort(Data A[],int length) {
2. int i, j; //i指向有序区最后一位,j指向无序区第一位
3. for (i=1; i4. j=i+1;
5. if(A[j].key < A[i].key) {
6. A[0]=A[j]; //存储待排序元素
7. while(A[0].key8. A[i+1] = A[i]; //查找在有序区中的插入位置,同时移动元素
9. i--; //查找时从有序区得最后一个元素先前查找
10. }
11. A[i+1]=A[0]; //将元素插入
12. }
13. i=j-1; //还原有序区指针
14. }
15.}
算法复杂度分析:
复杂度均为O(n2),稳定排序。
二、归并排序算法
算法思想:
它主要采用了分冶的思想,通过递归的方式不断的将两个有序的子序列归并成一个有序序列,直到整个序列有序为止。
该算法中每一层递归包括三个操作,分解(将n个元素分成n/2个元素的子序列)、解决(用归并排序法对两个子序列递归地排序)和合并(合并已经有序的子序列得到上层递归调用的排序结果)。
示意图解析:
设待排序的数组A[1]....A[7],则归并排序的操作过程如下所示
C++源码:
1.void Merge(int A[], int *temp,int l, int m, int h){
2. int lend = m;
3. int rstart = m+1;
4. int tem = l;
5. int num = h-1+1;
6. while(l<=lend && rstart<=h)
7. if (A[l]<=A[rstart])
8. temp[tem++]=A[l++];
9. else
10. temp[tem++]=A[rstart++];
11. while(l<=lend)
12. temp[tem++]=A[l++];
13. while(rstart<=h)
14. temp[tem++]=A[rstart++];
15. for(int i=h; i>h-num; i--)
16. A[i]=temp[i];
17.}
18.
19.void MSort(int A[], int *temp, int l, int h){
20. if (l21. int q = (l+h)/2;
22. MSort(A,temp,l,q);
23. MSort(A,temp,q+1,h);
24. Merge(A,temp,l,q,h);
25. }
26.}
27.
28.void MergeSort(int A[], int length){
29. int *temparray = new int[length];
30. if(temparray !
= NULL) {
31. MSort(A, temparray,