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

  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

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

01. Java的经典排序--选择排序--冒泡排序--折半查找(二分查找)

Java的经典排序--选择排序--冒泡排序--折半查找 选择排序 选择排序 3 2 1 5 8 0 1 3 2 5 8 1 1 2 3 5 8 2 1 2 3 5 8 3 1 2 3 5 8 public static void main(String[] args) { int[] arr={3,2,1,5,8}; selectSort(arr); for(int i = 0 ; i < arr.length ; i ++){ System.out.println(arr[i]) ; } }

七大内部排序算法总结(插入排序、希尔排序、冒泡排序、简单选择排序、快速排序、归并排序、堆排序)

 写在前面: 排序是计算机程序设计中的一种重要操作,它的功能是将一个数据元素的任意序列,重新排列成一个按关键字有序的序列.因此排序掌握各种排序算法非常重要.对下面介绍的各个排序,我们假定所有排序的关键字都是整数.对传入函数的参数默认是已经检查好了的.只是简单的描述各个算法并给出了具体实现代码,并未做其他深究探讨. 基础知识: 由于待排序的记录数量不同,使得排序过程中设计的存储器不同,可将排序方法分为两大类:一类是内部排序,指的是待排序记录存放在计算机随机存储器中进行的排序过程.另一类是外部排序,

几种排序方式的java实现(01:插入排序,冒泡排序,选择排序,快速排序)

以下为集中排序的java代码实现(部分是在引用别人代码): 插入排序(InsertSort): //代码原理 public static void iSort(int[] a){ for(int i = 1;i < a.length; i++){ if(a[i] < a[i-1]){ int temp = a[i]; while(temp < a[i-1]){ a[i] = a[i-1]; if(i-1 > 0){ i--; }else{ break; } } a[i-1] = t

冒泡排序,选择排序,快速排序

package com.hello; public class HelloJava { /** * 冒泡排序(通过一次一次的循环,根据相近两个值进行比较,将大的值往下移) * @author MR ZHANG * @param arr * @return */ public static void getBubbleSort(int[] arr){ for(int i = 1;i< arr.length-1;i++){ for(int j=0; j< arr.length-i;j++){ if

九种经典排序算法详解(冒泡排序,插入排序,选择排序,快速排序,归并排序,堆排序,计数排序,桶排序,基数排序)

综述 最近复习了各种排序算法,记录了一下学习总结和心得,希望对大家能有所帮助.本文介绍了冒泡排序.插入排序.选择排序.快速排序.归并排序.堆排序.计数排序.桶排序.基数排序9种经典的排序算法.针对每种排序算法分析了算法的主要思路,每个算法都附上了伪代码和C++实现. 算法分类 原地排序(in-place):没有使用辅助数据结构来存储中间结果的排序**算法. 非原地排序(not-in-place / out-of-place):使用了辅助数据结构来存储中间结果的排序算法 稳定排序:数列值(key)

JS冒泡排序,快速排序,二分查找

//冒泡排序 思想:一个数组双层循环,判断左右相邻的两个数值,大的在右小的在左,如果左的比右的大,双方替换位置 之所以要数组的长度减一,是因为数组是从0开始的,比如说一个数组有7个元素,它的长度为7,分别为a[0],a[1],a[2],a[3]a[4],a[5],a[6]这7个所以当你要取数组中最后一个a[6]时是需要用长度减1的而为什么要减i呢,则是因为你的冒泡排序是把最大的放到最后一位,比如第一次循环的时候进行排序完,最后一位是最大的了,根本没有必要在第二次循环当中把他在拿去比大小了吧,并且

基本排序算法(冒泡排序 选择排序 插入排序 快速排序 归并排序 基数排序 希尔排序)

冒泡排序 public static void bubbleSort(int[] arr){ int lgn = arr.length; for (int i = 0; i < lgn - 1; i++) { for (int j = 0; j < lgn - 1 - i; j++) { if(arr[j] > arr[j + 1]){ int temp = arr[j + 1]; arr[j + 1] = arr[j]; arr[j] = temp; } } } } 选择排序 publ

【数据结构】常用排序算法(包括:选择排序,堆排序,冒泡排序,选择排序,快速排序,归并排序)

直接插入排序: 在序列中,假设升序排序 1)从0处开始. 1)若走到begin =3处,将begin处元素保存给tmp,比较tmp处的元素与begin--处元素大小关系,若begin处<begin-1处,将begin-1处元素移动到begin:若大于,则不变化.再用tmp去和begin--处的元素用同样的方法去作比较,直至begin此时减少到数组起始坐标0之前结束. 3)以此类推,依次走完序列. 时间复杂度:O() 代码如下: //Sequence in ascending order  voi

选择排序&amp;冒泡排序&amp;折半查找

//选择排序 void test2(int a[],int len){ //每次找出一个最小值,最小值依次与原数组交换位置,通过下标来完成交换,最小值下标每次都在变,变量存储 //    假如第一个是最小值 int mine=0; int teamp=0; //    外层负责趟数 for (int i=0; i<len; i++) { //    假如每一次的第一个是最小值 mine=i; //    内层负责寻找每趟的最小值 //        每次起始比较值都不一样所以j=i+1,改变次数