C语言之冒泡排序、选择排序、折半查询、进制查表
时间:2022-06-11
本文章向大家介绍C语言之冒泡排序、选择排序、折半查询、进制查表,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
一、冒泡排序
//1、冒泡排序
/** 一组无序数字,进行从小到大排序
冒泡排序的过程:就是每个循环从第一个元素开始,相邻两个元素进行比较,前面的比后面的大,则进行值交换;
则第一次循环把最大值排到了最后,第二次循环把第二大的值排到了倒数第二位...以此类推;
把最大值想象成最大气泡,相邻气泡进行比较,较大气泡排到后面,最大气泡先冒到最后面。。。。
每次循环的比较个数次数从元素个数-1 到 1,假如5个元素,则循环比较的个数为:
****
***
**
*
*/
int arr[] = {88, 18, 99, 6, 72};
int arrCount = sizeof(arr) / sizeof(arr[0]);
printf("排序前的数组元素顺序为:n");
for (int i = 0; i < arrCount; i++) {
printf("%d ", arr[i]);
}
printf("nn开始进行冒泡排序:n");
//进行冒泡排序
for (int i = 0; i < arrCount; i++) {
for (int j = 0; j < arrCount - i - 1; j++) {
if (arr[j] > arr[j+1]){
int tmp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = tmp;
}
printf("*");
}
printf("n");
}
printf("排序后的数组元素排序为:n");
for (int i = 0; i < arrCount; i++) {
printf("%d ", arr[i]);
}
printf("nn");
/** 打印结果:
排序前的数组元素顺序为:
88 18 99 6 72
开始进行冒泡排序:
****
***
**
*
排序后的数组元素排序为:
6 18 72 88 99
*/
二、选择排序
//2、选择排序
/** 一组无序数字,进行从小到达排序
选择排序的过程:和冒泡排序有点相反的是每次循环中某一个元素和数组里面所有的元素进行比较,
然后每次循环都是把最小的排到最前面;
比如第一次循环把最小大排到最前面;第二次循环把第二小的排到第二位;
循环次数和冒泡排序一样
*/
int arr2[] = {11, 102, 99, 2, 82};
int arr2Count = sizeof(arr2) / sizeof(arr2[0]);
printf("排序前的数组元素顺序为:n");
for (int i = 0; i < arr2Count; i++) {
printf("%d ", arr2[i]);
}
printf("nn开始进行选择排序:n");
//进行冒泡排序
for (int i = 0; i < arr2Count; i++) {
for (int j = i+1; j < arr2Count; j++) {
if (arr2[i] > arr2[j]){
int tmp = arr2[i];
arr2[i] = arr2[j];
arr2[j] = tmp;
}
printf("*");
}
printf("n");
}
printf("排序后的数组元素排序为:n");
for (int i = 0; i < arr2Count; i++) {
printf("%d ", arr2[i]);
}
printf("nn");
/** 打印结果:
排序前的数组元素顺序为:
11 102 99 2 82
开始进行选择排序:
****
***
**
*
排序后的数组元素排序为:
2 11 82 99 102
*/
三、折半查询
#include <stdio.h>
#include <time.h>
int main(int argc, const char * argv[]) {
//3、折半查找:一组有序的数字,想快速找到某一个值对应的位置,进行插入或者删除,可以用到折半查询
int arr3[10000]; //定义一个一万个元素的数组
//给数组按顺序赋值
for (int i = 0; i < 10000; i++) {
arr3[i] = i * 2;
}
//问题1:查询1000值所在的位置、查询次数、耗时
//1.1 先按顺序查询
clock_t startTime = clock(); //开始时间
clock_t endTime = clock(); //结束时间
int selectCount = 0; //查询次数
int target = 1000;
for (int i = 0; i < 10000; i++) {
if (arr3[i] == target){
endTime = clock();
selectCount = i+1;
break;
}
}
printf("按顺序查询%d值位置共查询次数%d次, 耗时%ld毫秒 n", target, selectCount, endTime-startTime);
startTime = clock(), endTime = clock();
selectCount = 0;
//1.2 折半查询
int min = 0; //最小索引
int max = 10000; //最大索引
for (int i = 0; i < 10000; i++) {
int mid = (min + max)/2;
if (arr3[mid] > target){
max = mid; //如果数组最中间索引的值大于要查询的目标值,则最大索引设置为中间索引
}
else if (arr3[mid] < target){
min = mid; //如果数组最中间索引的值小于查询的目标值,则最小索引设置为中间索引
}
else{
endTime = clock();
selectCount = i + 1;
break;
}
}
printf("折半查询%d值的位置共查询次数%d次,耗时%ld毫秒 n", target, selectCount, endTime-startTime);
//问题2:查询18000值所在的位置、耗时、查询次数
//2.1 顺序查询
target = 18000;
startTime = clock(), endTime = clock();
selectCount = 0;
for (int i = 0; i < 10000; i++) {
if (arr3[i] == target){
endTime = clock();
selectCount = i+1;
break;
}
}
printf("按顺序查询%d值位置共查询次数%d次, 耗时%ld毫秒 n", target, selectCount, endTime-startTime);
startTime = clock(), endTime = clock();
selectCount = 0;
//2.2 折半查询
min = 0; //最小索引
max = 10000; //最大索引
for (int i = 0; i < 10000; i++) {
int mid = (min + max)/2;
if (arr3[mid] > target){
max = mid; //如果数组最中间索引的值大于要查询的目标值,则最大索引设置为中间索引
}
else if (arr3[mid] < target){
min = mid; //如果数组最中间索引的值小于查询的目标值,则最小索引设置为中间索引
}
else{
endTime = clock();
selectCount = i + 1;
break;
}
}
printf("折半查询%d值的位置共查询次数%d次,耗时%ld毫秒 n", target, selectCount, endTime-startTime);
//问题3:查询假如把数字1001插入数组中,应该插入到哪个位置,查询到这个位置耗时多久?
//3.1 顺序查询
target = 1001;
startTime = clock(), endTime = clock();
selectCount = 0;
int insertIndex = 0;
for (int i = 0; i < 10000-1; i++) {
if (arr3[i] < target && arr3[i+1] > target){
endTime = clock();
selectCount = i+1;
insertIndex = i;
break;
}
}
printf("按顺序查询%d值应插入位置索引:%d, 共查询次数%d次, 耗时%ld毫秒 n", target, insertIndex, selectCount, endTime-startTime);
startTime = clock(), endTime = clock();
selectCount = 0;
insertIndex = 0;
//3.2 折半查询
min = 0; //最小索引
max = 10000; //最大索引
for (int i = 0; i < 10000; i++) {
int mid = (min + max)/2;
if (arr3[mid] > target){
max = mid - 1; //如果数组最中间索引的值大于要查询的目标值,则最大索引设置为中间索引-1
}
else if (arr3[mid] < target){
min = mid + 1; //如果数组最中间索引的值小于查询的目标值,则最小索引设置为中间索引+1
}
if (min > max){
selectCount = i+1;
insertIndex = min;
break;
}
}
printf("折半查询%d值应插入位置索引:%d, 共查询次数%d次, 耗时%ld毫秒 n", target, insertIndex, selectCount, endTime-startTime);
//问题4:查询假如把数字18001插入数组中,应该插入到哪个位置,查询到这个位置耗时多久?
//4.1 顺序查询
target = 18001;
startTime = clock(), endTime = clock();
selectCount = 0;
insertIndex = 0;
for (int i = 0; i < 10000-1; i++) {
if (arr3[i] < target && arr3[i+1] > target){
endTime = clock();
selectCount = i+1;
insertIndex = i;
break;
}
}
printf("按顺序查询%d值应插入位置索引:%d, 共查询次数%d次, 耗时%ld毫秒 n", target, insertIndex, selectCount, endTime-startTime);
startTime = clock(), endTime = clock();
selectCount = 0;
insertIndex = 0;
//4.2 折半查询
min = 0; //最小索引
max = 10000; //最大索引
for (int i = 0; i < 10000; i++) {
int mid = (min + max)/2;
if (arr3[mid] > target){
max = mid - 1; //如果数组最中间索引的值大于要查询的目标值,则最大索引设置为中间索引-1
}
else if (arr3[mid] < target){
min = mid + 1; //如果数组最中间索引的值小于查询的目标值,则最小索引设置为中间索引+1
}
if (min > max){
selectCount = i+1;
insertIndex = max;
break;
}
}
printf("折半查询%d值应插入位置索引:%d, 共查询次数%d次, 耗时%ld毫秒 n", target, insertIndex, selectCount, endTime-startTime);
/** 打印日志(可以比较出来在这种应用场景下,折半查询比按顺序查询效率高):
按顺序查询1000值位置共查询次数501次, 耗时3毫秒
折半查询1000值的位置共查询次数13次,耗时1毫秒
按顺序查询18000值位置共查询次数9001次, 耗时30毫秒
折半查询18000值的位置共查询次数12次,耗时1毫秒
按顺序查询1001值应插入位置索引:500, 共查询次数501次, 耗时2毫秒
折半查询1001值应插入位置索引:501, 共查询次数14次, 耗时0毫秒
按顺序查询18001值应插入位置索引:9000, 共查询次数9001次, 耗时37毫秒
折半查询18001值应插入位置索引:9000, 共查询次数13次, 耗时1毫秒
*/
printf("n");
return 0;
}
四、进制查表(十进制转二进制、八进制、十六进制)
十进制数据,转成相对应的二进制、八进制、十六进制打印出来
#include <stdio.h>
#include <math.h>
void convertToBinary(int num); //十进制转成二进制
void convertToOctonary(int num); //十进制转成八进制
void convertToHexadecimal(int num); //十进制转成十六进制
void convertToOtherType(int num, int moveBitCount); //汇总,包括十进制转二进制、八进制、十六进制
int main(int argc, const char * argv[]) {
int a = 28, b = 158, c = 1188;
printf("... 十进制 ...n");
printf("%dn", a);
printf("%dn", b);
printf("%dn", c);
//测试数字转成二进制
printf("... 十进制转二进制 ...n");
convertToBinary(a);
convertToBinary(b);
convertToBinary(c);
//测试数字转成八进制
printf("... 十进制转八进制 ...n");
convertToOctonary(a);
convertToOctonary(b);
convertToOctonary(c);
//测试数字转成十六进制
printf("... 十进制转十六进制 ...n");
convertToHexadecimal(a);
convertToHexadecimal(b);
convertToHexadecimal(c);
//汇总方法,根据传入的参数把十进制转成对应的二进制、八进制、十六进制
printf("n");
printf("。。。十进制转二进制222 。。。n");
convertToOtherType(c, 1);
printf("。。。 十进制转八进制222。。。n");
convertToOtherType(c, 3);
printf("。。。 十进制转十六进制222。。。n");
convertToOtherType(c, 4);
/** 打印结果:
... 十进制 ...
28
158
1188
... 十进制转二进制 ...
0000 0000 0000 0000 0000 0000 0001 1100
0000 0000 0000 0000 0000 0000 1001 1110
0000 0000 0000 0000 0000 0100 1010 0100
... 十进制转八进制 ...
34
236
2244
... 十进制转十六进制 ...
1c
9e
4a4
。。。十进制转二进制222 。。。
10010100100
。。。 十进制转八进制222。。。
2244
。。。 十进制转十六进制222。。。
4a4
*/
return 0;
}
/** 把十进制转成二进制 */
void convertToBinary(int num){
int bitCount = sizeof(num) * 8;
for (int i = bitCount - 1; i >= 0; i--) {
printf("%d", num>>i & 1);
if (i % 4 == 0) printf(" ");
}
printf("n");
}
/** 把十进制转成八进制 */
void convertToOctonary(int num){
char chars[] = {'0', '1', '2', '3', '4', '5', '6', '7'};
//int bitCount = sizeof(num) * 8 / 3; //最多11位
char newCs[11] = {'0'};
int pos = 11;
while (num > 0) {
int result = num & 7; //取出3位二进制,转成八进制
newCs[--pos] = chars[result]; //从字符组中找到对应字符存入
num = num>>3; //右移3位
}
for (int i = pos; i < 11; i++) {
printf("%c", newCs[i]);
}
printf("n");
}
/** 把十进制转成十六进制 */
void convertToHexadecimal(int num){
char chars[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
//int bitCount = sizeof(num) * 8 / 4; //最多8位
char newCs[8] = {'0'};
int pos = 8;
while (num > 0) {
int result = num & 15; //每次取出4位二进制,转成十六进制
newCs[--pos] = chars[result]; //从字符组中找到对应字符存入
num = num>>4; //右移4位
}
for (int i = pos; i < 8; i++) {
printf("%c", newCs[i]);
}
printf("n");
}
/** 根据不同参数把十进制转成对应二进制、八进制、十六进制
参数:num = 要转化的十进制数字
moveBitCount : 每次需要位移的二进制位数量
*/
void convertToOtherType(int num, int moveBitCount){
char chars[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
int baseNum = pow(2, moveBitCount) - 1; //每次按位&的数字,转8进制为7,转16进制为15,转2进制为1
char newCs[32] = {'0'};
int pos = 32;
while (num > 0) {
int result = num & baseNum; //每次取出对应moveBitCount位二进制,转成其他进制
newCs[--pos] = chars[result]; //从字符组中找到对应字符存入
num = num>>moveBitCount; //右移4位
}
for (int i = pos; i < 32; i++) {
printf("%c", newCs[i]);
}
printf("n");
}
- mongodb生产环境(副本集模式)集群搭建配置
- ELK日志收集分析系统配置
- 【学术】如何在15分钟内建立一个深度学习模型?
- Elasticsearch(GEO)空间检索查询
- java spark-streaming接收TCP/Kafka数据
- hiveQL求差集
- hiveQL去重
- springboot高并发redis细粒度加锁(key粒度加锁)
- java使用spark/spark-sql处理schema数据
- redis的发布订阅模式pubsub
- linux命令和awk
- django集成celery之callback方式link_error和on_failure
- 使用beanstalkd实现定制化持续集成过程中pipeline
- 用SQLite查看编辑android导出的微信聊天记录
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Android EditText随输入法一起移动并悬浮在输入法之上的示例代码
- 突击并发编程JUC系列-并发容器ConcurrentHashMap
- android通过servlet服务器保存文件到手机
- Android开发疫情查询app(实例代码)
- 服务器上安装Mysql8.0
- Android AndroidX的迁移
- Android 应用Crash 后自动重启的方法小结
- Android 倒计时控件 CountDownView的实例代码详解
- 开启Scrapy爬虫之路
- Android Studio实现简单的QQ登录界面的示例代码
- Android 自定义SeekBar 实现分段显示不同背景颜色的示例代码
- 从约瑟夫环看循环链表
- Android 自定义LineLayout实现满屏任意拖动功能的示例代码
- Android scheme 跳转的设计与实现详解
- Android获取与设置系统环境变量的方法指南