明天考完最后一科数据库就放假咯,由于上个暑假外出打工已经好久没回家了,居然有点想家的感觉。最近复习比较忙,所以上网很少。时间过得也真快啊,转眼一个学期就过去了,来到CSDN大本营和大家认识也一个学期了啊!很感谢CSDN提供的这个平台让我们相聚一堂共同进步,共同扶持!数据结构转眼也学了一个学期咯,对于课本上的那些排序算法有点自己的心得。拿出来和大家分享一下,由于都是个人总结,难免会有些不尽如人意的地方,欢迎朋友们指正。(家里没网了,来年回复咯^_^)
引子:
三个数的排序:
Code:
1. #include <stdio.h>
2.
3. main()
4. {
5. void sort(int &x,int &y,int &z);
6. int a,b,c;
7. printf("请输入任意三个数:/n");
8. scanf("%d",&a);
9. scanf("%d",&b);
10. scanf("%d",&c);
11. sort(a,b,c);
12. printf("排序后:/n");
13. printf("%d %d %d/n",a,b,c);
14. return 0;
15. }
16.
17. void sort(int &x,int &y,int &z) //由于改变了x,y,z的值,所以要加引用,否则主函数中输出的是未排序的
18. {
19. int temp;
20. if(x>y)
21. {temp=x;x=y;y=temp;} //这里注意加上{};要不容易出错
22. if(x>z)
23. {temp=x;x=z;z=temp;}
24. if(y>z)
25. {temp=y;y=z;z=temp;}
26. }
简单排序:
1.简单选择:
Code:
1. //简单选择排序---选择排序法
2. #include <stdio.h>
3. #define size 10
4.
5. int main(void)
6. {
7. int i,j,min,temp;
8. int a[size]={49,37,25,16,84,79,56,62,10,2};
9.
10. for(i=0;i<size-1;i++)
11. {
12. min=i;
13. for(j=i+1;j<size;j++)
14. {
15. if(a[min]>a[j])
16. min=j; //得到的min为无序区最小的关键字的下标
17. }
18. if(min!=i)
19. {
20. temp=a[i];
21. a[i]=a[min];
22. a[min]=temp;
23. }
24. }
25.
26. for(i=0;i<size-1;i++)
27. {
28. printf("%d ",a[i]);
29. }
30. printf("%d/n",a[i]);
31. return 0;
32. }
这个选择排序法是“真正的选择排序”,谭浩强数中出现的选择排序其实并不完善,因为书中的选择排序并不是找到最小的与第一个数交换,而是每比较完一次如果小就交换。所以这个程序的比较次数相同但是交换次数不同,这个程序的交换次数少。而书中的是为了初学者更容易理解。但是两者的时间复杂度是一样的,都是O(n*n).
2.直接插入:
Code:
1. //直接插入
2. #include <stdio.h>
3. #define MAXSIZE 11
4.
5. typedef int KeyType;
6. typedef struct
7. {
8. KeyType key;
9. }RedType;
10. typedef struct
11. {
12. RedType r[MAXSIZE+1]; //r[0]闲置做哨兵用
13. int length;
14. }SqList;
15. /*直接插入:
16. 1.下标为0的位置用来做哨兵;
17. 2.第一个数默认是有序的,从第二个数开始排序;
18. 3.找出待排序的数应该插在前面的有序关键字的那个位置;
19. 4.插入待排序的数;
20. 5.重复3、4步知道全部有序
21. */
22. void InsertSort(SqList &L)
23. {
24. int i,j;
25. for(i=2;i<=L.length;++i)
26. {
27. if(L.r[i].key<L.r[i-1].key)
28. {
29. L.r[0]=L.r[i]; //将自身复制给L.r[0]作为哨兵
30. // L.r[i]=L.r[i-1]; //移动位置,空出插入的位置(可以并入下面的for循环中),如
31. for(j=i-1;L.r[0].key<L.r[j].key;--j)
32. {
33. L.r[j+1]=L.r[j]; //记录后移,空出插入的位置
34. }
35. L.r[j+1]=L.r[0]; //因为上面最后找到的位置是j的位置,然而最后会执行一次 --j是j减了一,所以这里必须再加上1即j+1的位置
36. }
37. }
38. }
39. int main(void)
40. {
41. int x;
42. SqList L;
43. L.length=MAXSIZE-1;
44. printf("请输入%d个数:/n",MAXSIZE-1);
45. for(int i=1;i<MAXSIZE-1;i++)
46. {
47. scanf("%d ",&L.r[i].key); //注意C语言的输入和输出格式规范
48. }
49. scanf("%d",&L.r[i].key);
50. InsertSort(L);
51. for(i=1;i<MAXSIZE-1;i++)
52. {
53. printf("%d ",L.r[i].key);
54. }
55. printf("%d/n",L.r[i].key);
56. return 0;
57. }
直接插入排序的思想是在将一个数插入到有序序列中,插入后的序列仍然要是有序的;用做排序是默认只有一个数时一定是有序的。然后将后面的数一个一个插入,直到整个序列都有序。这个算法经过了部分优化,减少了不必要的交换次数(将交换优化为移动),所以有一点难懂;这个算法是希尔排序算法的基础,且希尔排序算法也是经过部分优化的,理解了这个算法那么希尔排序算法也好理解了。
3.折半插入排序:
Code:
1. #include <stdio.h>
2. #define LISTSIZE 100
3.
4. typedef int KeyType;
5. typedef struct
6. {
7. KeyType key;
8. }DataType;
9.
10. typedef struct
11. {
12. DataType items[LISTSIZE];
13. int length;
14. }SqList;
15.
16. int CreateSqList(SqList &L)
17. {
18. int n;
19. printf("请输入你要创建的关键字总数:");
20. scanf("%d",&n);
21. printf("请输入%d个关键字:/n",n);
22. for(int i=0;i<n-1;i++)
23. {
24. scanf("%d ",&L.items[i]);
25. }
26. scanf("%d",&L.items[i]);
27. L.length=n;
28. return 0;
29. }
30.
31.
32. void BiInSertSort(SqList &L,int n) //注意这里的&L不能改写成L,这是这里L要改变,必须用到引用,要不然的话主函数中的L将不会改变
33. {
34. int i,j,low,upper,mid;
35. DataType p;
36. for(i=1;i<n;i++)
37. {
38. p=L.items[i];
39. low=0;
40. upper=i-1;
41. while(low<=upper) //找到要插入的位置
42. {
43. mid=(low+upper)/2;
44. if(p.key<L.items[mid].key)
45. upper=mid-1;
46. else
47. low=mid+1;
48. }
49. for(j=i-1;j>=low;j--) //移动位置
50. {
51. L.items[j+1]=L.items[j];
52. }
53. L.items[low]=p; //插入
54. }
55. }
56.
57.
58. int main(void)
59. {
60. SqList L;
61. CreateSqList(L);
62. BiInSertSort(L,L.length);
63. printf("折半插入排序后:/n");
64. for(int i=0;i<L.length-1;i++)
65. {
66. printf("%d ",L.items[i].key);
67. }
68. printf("%d/n",L.items[i].key);
69. return 0;
70. }
折半插入排序的思想可以借鉴折半查找;折半排序与直接插入排序相比,仅减少了关键字之间的比较次数,而数据元素的移动次数不变,因此折半插入排序的时间复杂度仍为O(n*n);
4.冒泡排序:
Code:
1. #include <stdio.h>
2. #define n 5
3. int main()
4. {
5. int i,j,temp;
6. int a[n]={2,6,8,4,1};
7.
8. for(i=0;i<n-1;i++) //理论依据跟是三个数的排序相同
9. {
10. for(j=0;j<n-i-1;j++)
11. {
12. if(a[j]>a[j+1])
13. {temp=a[j];a[j]=a[j+1];a[j+1]=temp;}
14. }
15. }
16. for(i=0;i<n;i++)
17. printf("%d ",a[i]);
18. printf("/n");
19. return 0;
20. }
这个算法的基础可以取自三个数的排序,其基本原理都是一样的;冒泡排序是三个数排序的推广。