c编程之排序
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编程之排序的更多相关文章
- Scala函数式编程实现排序算法
记得<Function Thinking>这本书中提到,现在的编程范式有两类,一类是“命令式编程”,另一类是“函数式编程”,现在我们最常使用的许多语言像c.c++.java都是命令式的,但 ...
- C++模板元编程----选择排序
目录 目录 前言 代码详解 数据的结构 数据的操作 分割向量 合并向量 寻找最大值 排序 总结 前言 模板在C++一直是比较神秘的存在.STL和Boost中都有大量运用模板,但是对于普通的程序员来说, ...
- DataGridView使用技巧十三:点击列头实现升序和降序排序
DataGridView 列有三种排序模式.每一列的排序模式是通过该列的 SortMode 属性指定的,该属性可以设置为以下的 DataGridViewColumnSortMode 枚举值之一. Da ...
- JavaScript排序,不只是冒泡
做编程,排序是个必然的需求.前端也不例外,虽然不多,但是你肯定会遇到. 不过说到排序,最容易想到的就是冒泡排序,选择排序,插入排序了. 冒泡排序 依次比较相邻的两个元素,如果后一个小于前一个,则交换, ...
- 排序 sort函数
sort函数见下表: 函数名 功能描述 sort 对给定区间所有元素进行排序 stable_sort 对给定区间所有元素进行稳定排序 partial_sort 对给定区间所有元素部分排序 partia ...
- sort函数的用法(C++排序库函数的调用)
对数组进行排序,在c++中有库函数帮我们实现,这们就不需要我们自己来编程进行排序了. (一)为什么要用c++标准库里的排序函数 Sort()函数是c++一种排序方法之一,学会了这种方法也打消我学习c+ ...
- 基于胜率矩阵的PageRank排序
在做博弈模型评估的时候,遇到一个问题是如何评价多个模型的优劣.例如我有训练好的三个围棋模型A,B,C,两两之间对打之后有一个胜负关系,如何对这三个模型进行排序呢?通常对于人类选手这种水平有波动的情 ...
- C语言范例学习04
第三章 算法 前言:许多人对算法的看法是截然不同的,我之前提到过了.不过,我要说的还是那句话:算法体现编程思想,编程思想指引算法. 同时,有许多人认为简单算法都太简单了,应当去学习一些更为实用的复杂算 ...
- ThinkPHP自动获取关键词(调用第三方插件)
ThinkPHP自动获取关键词调用在线discuz词库 先按照下图路径放好插件 方法如下 /** * 自动获取关键词(调用第三方插件) * @return [type] [description] * ...
随机推荐
- C#时间处理--DateTime和TimeSpan
DateTime dt = DateTime.Now; dt.ToString();//2005-11-5 13:21:25 dt.ToFileTime().ToString();//12775641 ...
- 那么如何添加网站favicon.ico图标
1. 获得一个favicon.ico的图标,大小为16px×16px最为合适 2. 将制作好的图标文件Favicon.ico上传到网站的根目录: 3. 在首页文件的html代码的头部中加入如下代码: ...
- C#中string[ ] args是什么意思,又有什么用呢
转载:http://blog.sina.com.cn/s/blog_8b7263d1010172jv.html C#控制台程序中static void Main(string[ ] args) str ...
- win7 C# winForm编程 savefiledialog 不能弹出保存窗体
public void ResMsg() { while (isRecMsg) { //准备一个数组 准备接收 ...
- 《安全参考》HACKCTO-201311-11
小编的话 “晴空一鹤排云去,便引诗情到碧宵” 11月是一个让人思绪飞扬.感慨万千的时节. 就在这时,在我们小伙伴的并肩奋战下,第十一期<安全参考>又跟大家见面了. 你还在为女朋友在购物狂欢 ...
- xmpp push篇一 广播消息
---广播给所有人--- 1. 登录xmpp admin 账户 2. sendpacket <message to="pandans.com(域名)" > <bo ...
- cxGrid使用汇总(一)
1. 去掉cxGrid中台头的Box 解决:在tableview1的ptionsview的groupbybox=false; 2.统计功能 解决:(1) tableview 1. tableview1 ...
- C#从数据库读取数据到DataSet并保存到xml文件
using System; using System.Data; using System.Xml; using System.Data.SqlClient; using System.IO; pub ...
- Simplified Memory Modle C/C++内存模型
最近学习c++看视频时,老师时常提到栈区堆区,搞不清楚,只能泪目,毕竟爱过...因此,接下来对此做些整理,方便回顾.(老师说:这个简化模型仅用于初学者示意,与实际模型并不完全一致) 1.stack(栈 ...
- 苏泊尔借助微软CRM提升客户满意度
企业背景 作为中国最大.全球第二的炊具研发制造商和中国小家电领先品牌,品质和创新一是苏泊尔矢志追求的企业理念,从火红点无油烟锅的发明到能做柴火饭的球釜IH饭煲的面世,苏泊尔用产品的创新和品质的承诺,不 ...