1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<string.h>
4 typedef struct Node{
5 int num[10];
6 int length;
7 char s[10];
8 }pNode;
9
10 //exchange
11 void swap(pNode *L,int m,int n)
12 {
13 int temp=0;
14 temp=L->num[m];
15 L->num[m]=L->num[n];
16 L->num[n]=temp;
17 }
18 //bubble sort
19 void Bubblesort(pNode *L)
20 {
21 int i=1;
22 int j=1;
23 for(j=1;j<=L->length;j++)
24 {
25 for(i=L->length-1;i>=j;i--)
26 {
27 if(L->num[i]>L->num[i+1])
28 swap(L,i,i+1);
29 }
30 }
31 }
32
33 //simple selection sort
34
35
36 //straight insertion sort
37
38
39 //heap sort
40 void HeapSort(pNode *L)
41 {
42 int i=1;
43 //for(i=L->length/2;i>0;i--) //this way is ok!!!!
44 for(i=L->length;i>0;i--)
45 Heap_adjust(L,i,L->length);
46 for(i=L->length;i>1;i--)
47 // for(i=L->length/2;i>0;i--)
48 {
49 swap(L,1,i);
50 Heap_adjust(L,1,i-1);
51 }
52 }
53 //heap adjust
54 void Heap_adjust(pNode *L,int s,int m)
55 {
56 int temp=0;
57 int j=0;
58 temp=L->num[s];
59 for(j=2*s;j<=m;j=j*2)
60 {
61 if(j<m&&(L->num[j]<L->num[j+1]))
62 ++j;
63 if(temp>L->num[j])
64 break;
65 L->num[s]=L->num[j];
66 s=j;
67 }
68 L->num[s]=temp;
69 }
70
71 //merging sort
72 void Mergesort(pNode *L)
73 {
74 Msort(L->num,L->num,1,L->length);
75 }
76 void Msort(int num1[],int num2[],int m,int n)
77 {
78 int flag;
79 int num3[11];
80 if(m==n)
81 {
82 num2[m]=num1[m]; //this is the recursion back condition
83 }
84 else
85 {
86 flag=(m+n)/2;
87 Msort(num1,num3,m,flag);
88 Msort(num1,num3,flag+1,n);
89 Merge(num3,num2,m,flag,n);
90 }
91 }
92 void Merge(int num1[],int num2[],int m,int flag,int n)
93 {
94 int j,k,l;
95 for(j=flag+1,k=m;m<=flag&&j<=n;k++)
96 {
97 if(num1[m]<num1[j])
98 {
99 num2[k]=num1[m++];
100 }
101 else
102 {
103 num2[k]=num1[j++];
104 }
105 }
106 if(m<=flag)
107 {
108 for(l=0;l<=flag-m;l++)
109 num2[k+l]=num1[m+l];
110 }
111 if(j<=n)
112 {
113 for(l=0;l<=n-j;l++)
114 num2[k+l]=num1[j+l];
115 }
116 }
117 //quick sort
118 void Qsort(pNode *L,int low,int high)
119 {
120 int flag;
121 if(low<high)
122 {
123 flag=Partition(L,low,high);
124 Qsort(L,low,flag-1);
125 Qsort(L,low+1,high);
126 }
127 }
128 int Partition(pNode *L,int low,int high)
129 {
130 int flag;
131 flag=L->num[low];
132 while(low<high)
133 {
134 while(low<high&&L->num[high]>=flag)
135 {
136 high--;
137 }
138 swap(L,low,high);
139 while(low<high&&L->num[low]<=flag)
140 {
141 low++;
142 }
143 swap(L,low,high);
144 }
145 return low;
146 }
147 //print
148 void Print(pNode *L)
149 {
150 int i=1;
151 for(;i<=L->length;i++)
152 {
153 printf("data:%d\n",L->num[i]);
154 }
155 }
156 int main()
157 {
158 pNode *L=(pNode*)malloc(sizeof(struct Node));
159 int num0[9]={50,10,90,30,70,40,80,60,20};
160 L->length=9;
161 int i=0;
162 for(;i<9;i++)
163 {
164 L->num[i+1]=num0[i];
165 }
166
167 //merge sort
168 //Mergesort(L);
169
170 //heap sort
171 //HeapSort(L);
172
173 //quick sort
174 //Qsort(L,1,9);
175
176 //bubble sort
177 Bubblesort(L);
178 Print(L);
179
180 return 0;
181 }

  主要实现了冒泡排序、堆排序、归并排序、快速排序。其中归并排序、快速排序运用了递归算法。

  冒泡排序:主要是用了双重循环,第一层循环控制整个排序的步长,第层循环在大于第一层循环的基础上从顺序表末端依次比较,将最小或者最大的数排到当前起一层循环的开始处。

  堆排序

  堆是具有下列性质的完全二叉树:每个节点的值都大于或等于其左右孩子节点的值,称为大顶堆,或者每个节点的值都小于或等于其左右孩子的值,称为小顶堆。

  步骤1、将数据建立成一个大顶堆,利用data(i)>=data(2i)、data(i)>=data(2i+1)主要就是要保证每个节点要大于其左右孩子

  步骤2、根据步骤1建立的大顶堆,我们可以知道该完全二叉树的顶堆是最大值,那么我们把最大值换到这颗树的最底端,这样就完成了将最大的数放在最后面的一次交换,我们把最底端的数换到最顶端就会出现不符合大顶堆数据结构的情况于是我们需要调整。如代码:

 53 //heap adjust
54 void Heap_adjust(pNode *L,int s,int m)
55 {
56 int temp=0;
57 int j=0;
58 temp=L->num[s];
59 for(j=2*s;j<=m;j=j*2)
60 {
61 if(j<m&&(L->num[j]<L->num[j+1]))
62 ++j;
63 if(temp>L->num[j])
64 break;
65 L->num[s]=L->num[j];
66 s=j;
67 }
68 L->num[s]=temp;
69 }

  我们对Heap_adjust(pNode *L,int s,int m)函数传递的参数是Heap_adjust(L,1,i-1),相当于s=1,m=i-1,我们调整的范围就是:从我们刚刚交换数据的最顶端到最底端减1,即1<=x<i-1;

  调整的目的就是保证目前的完全二叉树是一个大顶堆,最顶端的数一定是最大的,只有这样后面我们才可以不断地将顶端的数据交换到底端。调整的方法就是每次先找到节点然后在找到这个节点的左右孩子,所以变化是以2的倍数变化的,只有这样才符合data(i)>=data(2i)、data(i)>=data(2i+1)这个公式。

  归并排序

  归并排序:假设初始序列含有n个记录,则可以看成是n个有序的序列,每个子序列的长度为1,然后归并得到n/2个长度为2或者为1的有序子序列;再归并......直到得到一个长度为n的有序序列为止,这种排序方法称为2路归并排序。

  步骤1、将提供的数据分成两段,如我们提供的数据是50、10、90、30、70、40、80、60、20一共9个数字

第一次调用Msort(num1,num3,m,flag)函数,m=1,flag=9将1-9分成1-5、6-9两段,然后1-5这段数据继续迭代m=1,flag=5,将1-5分成1-3、4-5两段,然后1-3继续迭代m=1,flag=3,将1-3分成1-2,3-3两段,然后1-2继续迭代m=1,flag=2,将1-2分成1-1,2-2然后我们有一个递归返回的判断 num2[m]=num1[m],此时m=1,n=1递归返回第一次,程序执行1-2范围内1-1的另一半2-2,m=n递归返回第二次,然后在将这两个数调用Merge()函数做一个归并,第一次归并,至此1-2分成的两段就完成了归并。

然后程序就继续往下执行就是函数从1-3范围的另一半3-3,因为m=n所以递归返回,直接执行1-2,3-3的归并,这样1-3就完成了归并。

递归继续返回应该是1-5范围的另一半4-5进行递归调用,因为1-3我们已经完成了归并,m=4,n=5将4-5分成4-4,5-5,即数据段的两段都直接递归返回,然后将s=4,s=5分别存入num2数组中:num2[m]=num1[m]; //this is the recursion back condition,这样num2[4]、num2[5]都存放了值,然后程序已经执行了87行、88行代码,所以程序继续执行89行代码,也就是对num2[4]、num2[5]进行一个归并,然后递归返回将1-3,4-5这两段数据调用89行代码做一个归并,至此1-9分成的两段1-5,6-9前半段已经完成了排序,程序也已经递归返回到了最开始执行Msort函数时的状态,即第一调用Msort函数分成的1-5,6-9段这儿,相当于前面的所有步骤在第一次进入Msort函数后将1-9分成了1-5,6-9两段,然后m=1,flag=5调用87行代码,这个递归调用返回后继续执行88行代码。

  后面程序继续执行88行代码然后重复数据段1-5的步骤完成6-9的数据排序,直到88行代码递归返回了最后就只有1-5,6-9段的数据合并了那么执行89行代码完成最后的数据合并就完成了整个归并排序。可以看出整个过程是不断在分段、合并,最后程序递归返回到最初的分段然后合并两个长的数据段就完成了归并排序。所以在写程序时Merge函数时我们可以想象这已经是两个分好的大数据段了,我们需要对这两个数据段进行合并,这样对里面的变量变化范围就很好判断,而且思路顿时清醒很多,如果绕道递归里面去了将会十分的复杂,同时要注意这个Msor函数里面有两次递归调用,其执行顺序是一个调用一次Msort函数,会包含这个函数里面的所有内容,也就是说87行的函数每一次递归返回都会调用一次88、89行代码然后完成一次归并,因为在程序里面一次函数调用会形成一个栈帧,这个栈帧包含了函数的所有内容包括变量,函数的返回地址等等,所以Msort函数每递归返回一次,都会依次去执行后面的代码,也就是数据段的另一个范围,然后调用89行代码把这两个数据段完成合并。

 87                   Msort(num1,num3,m,flag);
88 Msort(num1,num3,flag+1,n);
89 Merge(num3,num2,m,flag,n);

  快速排序

  快速排序:通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序的目的。

  快排的关键点就是不断地变化关键字的位置,也就是这个关键字左边的数小于关键字,右边的数大于关键字,不断变化这个关键字的位置最终完成排序。

    

c编程之排序的更多相关文章

  1. Scala函数式编程实现排序算法

    记得<Function Thinking>这本书中提到,现在的编程范式有两类,一类是“命令式编程”,另一类是“函数式编程”,现在我们最常使用的许多语言像c.c++.java都是命令式的,但 ...

  2. C++模板元编程----选择排序

    目录 目录 前言 代码详解 数据的结构 数据的操作 分割向量 合并向量 寻找最大值 排序 总结 前言 模板在C++一直是比较神秘的存在.STL和Boost中都有大量运用模板,但是对于普通的程序员来说, ...

  3. DataGridView使用技巧十三:点击列头实现升序和降序排序

    DataGridView 列有三种排序模式.每一列的排序模式是通过该列的 SortMode 属性指定的,该属性可以设置为以下的 DataGridViewColumnSortMode 枚举值之一. Da ...

  4. JavaScript排序,不只是冒泡

    做编程,排序是个必然的需求.前端也不例外,虽然不多,但是你肯定会遇到. 不过说到排序,最容易想到的就是冒泡排序,选择排序,插入排序了. 冒泡排序 依次比较相邻的两个元素,如果后一个小于前一个,则交换, ...

  5. 排序 sort函数

    sort函数见下表: 函数名 功能描述 sort 对给定区间所有元素进行排序 stable_sort 对给定区间所有元素进行稳定排序 partial_sort 对给定区间所有元素部分排序 partia ...

  6. sort函数的用法(C++排序库函数的调用)

    对数组进行排序,在c++中有库函数帮我们实现,这们就不需要我们自己来编程进行排序了. (一)为什么要用c++标准库里的排序函数 Sort()函数是c++一种排序方法之一,学会了这种方法也打消我学习c+ ...

  7. 基于胜率矩阵的PageRank排序

      在做博弈模型评估的时候,遇到一个问题是如何评价多个模型的优劣.例如我有训练好的三个围棋模型A,B,C,两两之间对打之后有一个胜负关系,如何对这三个模型进行排序呢?通常对于人类选手这种水平有波动的情 ...

  8. C语言范例学习04

    第三章 算法 前言:许多人对算法的看法是截然不同的,我之前提到过了.不过,我要说的还是那句话:算法体现编程思想,编程思想指引算法. 同时,有许多人认为简单算法都太简单了,应当去学习一些更为实用的复杂算 ...

  9. ThinkPHP自动获取关键词(调用第三方插件)

    ThinkPHP自动获取关键词调用在线discuz词库 先按照下图路径放好插件 方法如下 /** * 自动获取关键词(调用第三方插件) * @return [type] [description] * ...

随机推荐

  1. shell脚本中的特殊符号

    1.{} 大括号:用法一:通配符扩展eg: ls my_{finger,toe}s这条命令相当于如下命令的组合:ls my_fingers my_toeseg: mkdir {userA,userB, ...

  2. android版猜拳游戏源码分享

    android版猜拳游戏源码分享安卓版猜拳游戏源码,该文件中带有安装测试包的,这个游戏源码比较简单的,现在有两个代码,一个自定义VIEW的,一个就是普通的imageView图片,游戏非常适合一些新手的 ...

  3. 带Left Join的SQL语句的执行顺序

    基础的SQL执行顺序 SQL语句执行的时候是有一定顺序的.理解这个顺序对SQL的使用和学习有很大的帮助. 1.from 先选择一个表,或者说源头,构成一个结果集. 2.where 然后用where对结 ...

  4. Ubuntu 14.04 – How to install xrdp in Ubuntu 14.04

    http://c-nergy.be/blog/?p=5305 Hello World, Ubuntu 14.04 has been released on April 17th 2014 and we ...

  5. mvc路由设置参数配置类似于url重写

    1.新建的mvc项目中Global.asax 2.在另外一个控制器中的视图中 3. 4.

  6. 安装CMS遇到php5.3的问题

    DedeCMS Error: (PHP 5.3 and above) Please set 'request_order' ini value to include C,G and P (recomm ...

  7. PHP中数据库的连接

    <?php //1.链接MySQL服务器 $conn = mysql_connect("localhost", "root" , 199452); //2 ...

  8. Git一张图学习

  9. HBase从hdfs导入数据

    需求:将HDFS上的文件中的数据导入到hbase中 实现上面的需求也有两种办法,一种是自定义mr,一种是使用hbase提供好的import工具 一.hdfs中的数据是这样的 每一行的数据是这样的id ...

  10. 与谷歌测试工程师的对话 - from Google Testing Blog

    Conversation with a Test Engineer by Alan Faulner Alan Faulner谷歌的一名测试工程师,他工作在DoubleClick Bid Manager ...