码迷,mamicode.com
首页 > 编程语言 > 详细

选择排序、冒泡排序、快速排序和二分查找的C语言实现

时间:2020-02-01 15:56:52      阅读:89      评论:0      收藏:0      [点我收藏+]

标签:排序数组   tchar   main   函数   必须   arch   turn   游标   type   

  1 #include <stdio.h>
  2 
  3 #define ASC 0 //升序,从左到右,从小到大
  4 #define DESC 1 //降序,从左到右,从大到小
  5 #define TRUE 1 //布尔值,真
  6 #define FALSE 0 //布尔值,假
  7 
  8 typedef int datatype; //定义数组元素的类型,这里暂定为int
  9 
 10 void selectSort(datatype array_to_sort[], int length, int mode); //选择排序原型
 11 void bubbleSort(datatype array_to_sort[], int length, int mode); //冒泡排序原型
 12 void quickSort(datatype array_to_sort[], int left, int right, int mode); //快速排序原型
 13 int binarySearch(datatype array_to_search[], int length, datatype value_to_search); //二分查找原型
 14 
 15 int main(){
 16     int i;
 17     datatype myarr[8]={3,100,32,49,15,6,17,8};
 18 
 19     for (i=0;i<8;i++){
 20         printf("%d ",myarr[i]);
 21     }
 22 
 23     //selectSort(myarr,8,DESC);
 24     //bubbleSort(myarr,8,ASC);
 25     quickSort(myarr,0,7,ASC);
 26 
 27     putchar(\n);
 28 
 29     for (i=0;i<8;i++){
 30         printf("%d ",myarr[i]);
 31     }
 32 
 33     putchar(\n);
 34 
 35     printf("find value 100 at: %d\n",binarySearch(myarr,8,100));
 36 
 37     return 0;
 38 }
 39 
 40 void selectSort(datatype array_to_sort[], int length, int mode){
 41     /*
 42     直接选择排序是一种不稳定的排序算法,
 43     例如:5 2 5 8,按照降序排序,第一个元素5和后序三个元素进行比较,发现第四个元素8大于自己,进行交换,这时,原本排在第一的5,现在变成了第二
 44     下面的,冒泡排序是稳定排序、快速排序是不稳定排序
 45     */
 46     int i,j,k; //i、j和k保存的都是下标
 47     datatype tmp;
 48     for (i=0;i<length-1;i++){
 49         k=i; //假设当前元素就是最值(最小或最大值)
 50         for (j=i+1;j<length;j++){ //注意,内循环条件是j<length而不是j<length-1,否则会导致数组的最后一个元素不参与比较
 51             //将后续元素与当前元素进行比较
 52             switch(mode){
 53             case ASC: //升序
 54                 if (array_to_sort[k]>array_to_sort[j])
 55                     k=j; //找到比当前元素更小值的元素,刷新下标
 56                 break;
 57             case DESC: //降序
 58                 if (array_to_sort[k]<array_to_sort[j])
 59                     k=j; //找到比当前元素更大值的元素,刷新下标
 60                 break;
 61             }
 62         }
 63         if (i!=k){ //不相等说明存在刷新,也就是说有比当前元素更小或更大的元素,交换它们
 64             tmp=array_to_sort[i]; array_to_sort[i]=array_to_sort[k]; array_to_sort[k]=tmp;
 65         }
 66     }
 67 }
 68 
 69 void bubbleSort(datatype array_to_sort[], int length, int mode){
 70     /*
 71     array_to_sort:待排序数组(原数组)
 72     length:待排序数组的长度
 73     mode:排序的类型,0或ASC表示升序,1或DESC表示降序
 74     注意,不能使用 sizeof array_to_sort 来获取待排序数组的长度,因为array_to_sort不是数组名,而是指针,只有对数组名进行sizeof运算才能得到此数组元素的个数
 75     在形参上的中括号并非表示数组,而是表示指针,因为编译器会自动识别并转换,相当于datatype *array_to_sort
 76     本函数将修改原数组
 77     冒泡排序的两个优化:
 78     1.将内循环的条件从j<length-1修改为j<length-1-i,减少了内循环的次数,假设待排序元素有N个,优化前共需要循环(N-1)^2次,优化后只需((1+(N-1))*(N-1))/2次
 79     2.如果有一趟循环没有发生元素交换,则说明这时的数组已经有序,不必再进行循环了
 80     */
 81     int i,j,flag1,flag2; //flag1是本次循环是否已经有序的标志,flag2是本次循环是否需要发生交换的标志
 82     datatype tmp; //用于交换的临时变量
 83     flag1=TRUE; //初始为真,以便能够进入首次循环,TRUE表示数组现在还是无序的,FALSE表示数组已经是有序的
 84     flag2=FALSE; //初始为假,假设不需要交换
 85     for (i=0; i<length-1 && flag1; i++){ //N个元素只需要循环N-1次
 86         flag1=FALSE; //每次循环先置为假,假设这次循环的元素已有序
 87         for (j=0;j<length-1-i;j++){ //-i是因为冒泡排序的每次外循环已将本次的最大或最小数归位了,而归位的数不必再参与排序
 88             switch (mode){
 89             case ASC:
 90                 if (array_to_sort[j]>array_to_sort[j+1])
 91                     //如果前面存在较大的元素,则需要交换,以便将它往后移,将标志flag2置为真
 92                     flag2=TRUE;
 93                 break;
 94             case DESC:
 95                 if (array_to_sort[j]<array_to_sort[j+1])
 96                     //如果前面存在较小的元素,则需要交换,以便将它往后移,将标志flag2置为真
 97                     flag2=TRUE;
 98                 break;
 99             }
100             if (flag2){ //如果标志为真,则说明上面比较中出现了需要交换的元素
101                 //下面3行代码用于实现交换
102                 tmp=array_to_sort[j];
103                 array_to_sort[j]=array_to_sort[j+1];
104                 array_to_sort[j+1]=tmp;
105                 flag1=TRUE; //发生了交换,将flag1置为真
106                 flag2=FALSE; //将flag2置为假,即重置flag2,以便用于下次判断
107             }
108         }
109     }
110 }
111 
112 void quickSort(datatype array_to_sort[], int left, int right, int mode){
113     /*
114     快速排序的基本思想:每次从待排序数组中找一个基数并把它归位,接下来对基数的左右子数组继续执行相同的操作,直到某个基数的左或右子数组只有一个元素或不存在,这时函数返回
115     升序:把小于基数的元素放在基数左侧,把大于基数的元素放在基数右侧
116     降序:把大于基数的元素放在基数左侧,把小于基数的元素放在基数右侧
117     left:待排序数组的首元素下标
118     right:待排序数组的最后一个元素下标
119     */
120     int i,j,base,tmp;
121     if (left>=right) return; //当left>right说明此子数组的范围无效,当left=right说明此子数组只有一个元素,都直接返回
122     base=array_to_sort[left]; //假设基数是本次待排序数组的首元素的值
123     i=left; j=right; //设置左右游标的初始值
124     while (i<j){ //一直循环,直到i和j相遇,说明找到了该基数最终排序的位置,循环结束后将该基数归位
125         switch (mode){
126         case ASC: //升序
127              //顺序很重要,先从右往左
128             while (array_to_sort[j]>=base && i<j) j--; //找一个比基数小的数,i<j用于判断i和j是否相遇,不相遇时继续找,下同
129             //再从左往右
130             while (array_to_sort[i]<=base && i<j) i++; //找一个比基数大的数
131             break;
132         case DESC: //降序
133             //顺序很重要,先从右往左
134             while (array_to_sort[j]<=base && i<j) j--; //找一个比基数大的数
135             //再从左往右
136             while (array_to_sort[i]>=base && i<j) i++; //找一个比基数小的数
137             break;
138         }
139         //如果i和j没相遇,就交换找到的两个数
140         if (i<j){
141             tmp=array_to_sort[i]; array_to_sort[i]=array_to_sort[j]; array_to_sort[j]=tmp;
142         }
143     }
144     //下面2行代码用于将基数归位,此时的i与j的值相同,i所表示的下标就是基数归位的位置
145     array_to_sort[left]=array_to_sort[i]; //将原本存储基数的元素用找到的基数归位的位置的元素覆盖
146     array_to_sort[i]=base; //基数归位
147     quickSort(array_to_sort,left,i-1,mode); //左递归,继续处理左侧待排序子数组
148     quickSort(array_to_sort,i+1,right,mode); //右递归,继续处理右侧带排序子数组
149 }
150 
151 int binarySearch(datatype array_to_search[], int length, datatype value_to_search){
152     /*
153     二分查找(折半查找)的数组必须是有序的(升序或降序),本函数要求数组是升序的
154     本函数返回的是找到的元素的下标
155     left、right和mid存储的是数组的下标
156     注意:本函数实现的二分查找是不稳定的,如果数组存在多个相同的值,不确定返回其中的哪一个
157     */
158     int left,right,mid; //left和right共同确定数组当前的查找范围,mid存储当前范围的中间元素的下标
159     left=0; right=length-1; //初始的范围自然是整个数组
160     while (left<=right){
161         mid=(left+right)/2; //取这段范围内的中间元素的下标,对于C语言,如果除法两侧的操作数类型都是整型,则执行整除
162         if (value_to_search<array_to_search[mid])
163             right=mid-1; //要找的值比中间元素的值还要小,则让right左移当前范围的一半
164         else if (value_to_search>array_to_search[mid])
165             left=mid+1; //要找的值比中间元素的值还要大,则让right右移当前范围的一半
166         else //找到
167             return mid; //返回找到元素的下标
168     }
169     return -1; //未找到则返回下标-1
170 }

 

选择排序、冒泡排序、快速排序和二分查找的C语言实现

标签:排序数组   tchar   main   函数   必须   arch   turn   游标   type   

原文地址:https://www.cnblogs.com/ryzz/p/12248612.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!