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 }
原文地址:https://www.cnblogs.com/ryzz/p/12248612.html
时间: 2024-11-08 22:34:01