【算法】
算法是用来解决常见问题的方法
同一个问题可以采用多种方法解决,不同方法使用于不同的环境
【排序算法】
排序指的是把一组数字按照某个顺序排列好
排序算法分很多次重复执行,每次负责把一个数字放在合适的位置上
为了实现以上效果可以"先确定数字,然后查找位置,反之也可以"
通过不断的调整两个数字的相互顺序最终把合适的数字放在合适的位置上
1. 冒泡排序算法(必须掌握)
每次把一个数字放在最前边或最后边的位置上(根据位置找数字)
不断调整相邻两个数字的顺序最终把一个数字放在最前或最后的位置上
<函数演示>
2. 选择排序算法
3. 插入排序算法
采用先确定数字然后找位置的方法,每次把第一个或最后一个排序好的数字作为选定数字,把它插入到已经排序好的数字中合适的位置
每次把选定数字和一个相邻存储区的内容做顺序调整,直到它被放在合适的位置上
<函数演示>
4. 快速排序算法(最快最好,必须掌握)
采用"先确定数字然后找位置"的方法
从没有处理过的所有数字两端选择一个作为基准数字
把基准数字和所有其他数字进行顺序调整,比基准数字大的放一边,比基准数字小的放另一边
每次对没有处理过的数字中"两端的数字进行顺序调整"(这两端的数字一定包含基准数字)
在调整完两个数字的顺序后把不是基准数字的数字排除在外
<模拟快速排序过程>
[40]50 20 30 60 80 70[90] - 40(基准数字)
[40]50 20 30 60 80[70]90
[40]50 20 30 60[80]70 90
[40]50 20 30[60]80 70 90
[40]50 20[30]60 80 70 90
30[50]20[40]60 80 70 90
30[40|20]50 60 80 70 90
30 20[40]50 60 80 70 90 //40就在排序好的正确位置上
[30|20]40 50 60 80 70 90 - 30(基准数字)
[20|30]40 50 60 80 70 90
20 30 40 50 60[80|70]90 - 20/50/60/不动 - 80(基准数字)
20 30 40 50 60[70|80]90 //排好序
<函数演示>
【查找算法】
查找算法可以从一组数字里找到某一个数字所在的位置
1. 顺序查找
依次把每个数字和要查找的数字做对比,直到找到为止
如果"数字的排列没有规律"就只能采用这种方法查找
2. 折半查找算法
如果所有"数字已经按照某种顺序排列好"就可以用中间位置的数字和目标数字做对比,这样可以一次排除掉一半的数字
重复这个过程就可以很快找到目标数字的位置
<函数演示>
算法是用来解决常见问题的方法
同一个问题可以采用多种方法解决,不同方法使用于不同的环境
【排序算法】
排序指的是把一组数字按照某个顺序排列好
排序算法分很多次重复执行,每次负责把一个数字放在合适的位置上
为了实现以上效果可以"先确定数字,然后查找位置,反之也可以"
通过不断的调整两个数字的相互顺序最终把合适的数字放在合适的位置上
1. 冒泡排序算法(必须掌握)
每次把一个数字放在最前边或最后边的位置上(根据位置找数字)
不断调整相邻两个数字的顺序最终把一个数字放在最前或最后的位置上
<函数演示>
/*代码*/ "冒泡排序算法"
#include <stdio.h>
void bubble_sort(int *p_num, int size) {
int i = 0, j = 0, tmp = 0;
for(i = 1; i < size; i++) { //循环次数是 size - 1
int flag = 1; //标记,如果本身有序就不执行内层循环
for(j = 0; j < size - i; j++) { //轮数+当前轮循环次数=size
if(*(p_num + j) > *(p_num + j + 1)) {
tmp = *(p_num + j);
*(p_num + j) = *(p_num + j + 1);
*(p_num + j + 1) = tmp;
flag = 0;
}
}
if(flag)
break;
}
}
int main() {
int arr[] = {23, 15, 7, 17, 27, 5, 33, 25, 19};
bubble_sort(arr, sizeof(arr)/sizeof(int));
int i = 0;
for(i = 0; i < sizeof(arr)/sizeof(int); i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
2. 选择排序算法
void selectionSort(int[] list) {
// 需要遍历获得最小值的次数
// 要注意一点,当要排序 N 个数,已经经过 N-1 次遍历后,已经是有序数列
for (int i = 0; i < list.length - 1; i++) {
int temp = 0;
int index = i; // 用来保存最小值得索引
// 寻找第i个小的数值
for (int j = i + 1; j < list.length; j++) {
if (list[index] > list[j]) {
index = j;
}
}
// 将找到的第i个小的数值放在第i个位置上
temp = list[index];
list[index] = list[i];
list[i] = temp;
System.out.format("第 %d 趟:\t", i + 1);
printAll(list);
}
}
3. 插入排序算法
采用先确定数字然后找位置的方法,每次把第一个或最后一个排序好的数字作为选定数字,把它插入到已经排序好的数字中合适的位置
每次把选定数字和一个相邻存储区的内容做顺序调整,直到它被放在合适的位置上
<函数演示>
/*代码*/ "插入排序算法"
#include <stdio.h>
int *insert_sort(int *p_num, int size) {
int num = 0, num1 = 0, tmp = 0;
for(num = 1; num < size; num++) {
//每次把下标为num的存储区内容插入到前面
for(num1 = num; num1 >= 1; num1--) {
//把下标为num1和num1-1的两个存储区内容做顺序调整
if(*(p_num + num1 - 1) > *(p_num + num1)) {
tmp = *(p_num + num1 - 1);
*(p_num + num1 - 1) = *(p_num + num1);
*(p_num + num1) = tmp;
}
else
break; //把前面比它小的停止执行,不需要对比交换
}
}
return p_num;
}
int main() {
int arr[] = {23, 15, 7, 17, 27, 5, 33, 25, 19};
int num = 0;
insert_sort(arr, 9);
for(num = 0; num < 9; num++) {
printf("%d ", arr[num]); //5 7 15 17 19 23 25 27 33
}
printf("\n");
return 0;
}
4. 快速排序算法(最快最好,必须掌握)
采用"先确定数字然后找位置"的方法
从没有处理过的所有数字两端选择一个作为基准数字
把基准数字和所有其他数字进行顺序调整,比基准数字大的放一边,比基准数字小的放另一边
每次对没有处理过的数字中"两端的数字进行顺序调整"(这两端的数字一定包含基准数字)
在调整完两个数字的顺序后把不是基准数字的数字排除在外
<模拟快速排序过程>
[40]50 20 30 60 80 70[90] - 40(基准数字)
[40]50 20 30 60 80[70]90
[40]50 20 30 60[80]70 90
[40]50 20 30[60]80 70 90
[40]50 20[30]60 80 70 90
30[50]20[40]60 80 70 90
30[40|20]50 60 80 70 90
30 20[40]50 60 80 70 90 //40就在排序好的正确位置上
[30|20]40 50 60 80 70 90 - 30(基准数字)
[20|30]40 50 60 80 70 90
20 30 40 50 60[80|70]90 - 20/50/60/不动 - 80(基准数字)
20 30 40 50 60[70|80]90 //排好序
<函数演示>
/*代码*/ "快速排序算法"
#include <stdio.h>
int *quick_sort(int *p_num, int size) {
int base = *p_num; //数组第一个存储区的数字作为基准数字
int *p_start = p_num, *p_end = p_num + size - 1, tmp = 0;
if(size <= 1) { //处理不可分解的情况,没有元素和只有1个元素
return p_num;
}
while(p_start < p_end) { //指针移动的位置还没有向中间碰到一起
if(*p_start > *p_end) { //对没处理过的数字中前>后的进行调换
tmp = *p_start;
*p_start = *p_end;
*p_end = tmp;
}
if(*p_start == base) { //把两端数字中非基准数字排除在外
p_end--; //基准数字在前
}
else {
p_start++; //基准数字在后
}
}
quick_sort(p_num, p_start - p_num); //递归左半边快速排序
quick_sort(p_start + 1, size - (p_start - p_num + 1)); //递归右
return p_num;
}
int main() {
int arr[] = {23, 15, 7, 17, 27, 5, 33, 25, 19};
int num = 0;
quick_sort(arr, 9);
for(num = 0; num < 9; num++) {
printf("%d ", arr[num]); //5 7 15 17 19 23 25 27 33
}
printf("\n");
return 0;
}
【查找算法】
查找算法可以从一组数字里找到某一个数字所在的位置
1. 顺序查找
依次把每个数字和要查找的数字做对比,直到找到为止
如果"数字的排列没有规律"就只能采用这种方法查找
2. 折半查找算法
如果所有"数字已经按照某种顺序排列好"就可以用中间位置的数字和目标数字做对比,这样可以一次排除掉一半的数字
重复这个过程就可以很快找到目标数字的位置
<函数演示>
/*代码*/
#include <stdio.h>
//折半查找法,找到的是目标数字的位置
int *half_search(int *p_num, int size, int num) {
int *p_start = p_num, *p_end = p_num + size - 1, *p_mid = NULL;
while(p_start <= p_end) { //如果没找到循环就退出
p_mid = p_start + (p_end - p_start + 1) / 2; //中间位置
if(*p_mid == num) { //中间位置存储区内容就是要查找的数字
return p_mid;
}
else if(*p_mid > num) { //中间位置存储区内容比查找的数字大
p_end = p_mid - 1;
}
else { //中间位置存储区内容比要查找的数字小
p_start = p_mid + 1;
}
}
return NULL;
}
//递归函数改写
int *half_search_rec(int *p_start, int *p_end, int num) {
int *p_mid = NULL;
if(p_start > p_end) {
return NULL;
}
p_mid = p_start + (p_end - p_start + 1)/2;
if(*p_mid == num) {
return p_mid;
}
else if(*p_mid > num) {
return half_search_rec(p_start, p_mid - 1, num);
}
else {
return half_search_rec(p_mid + 1, p_end, num);
}
}
int main() {
int arr[] = {3, 8, 11, 13, 16, 19, 21, 25, 32, 36, 44};
int *p_num = half_search(arr, sizeof(arr)/sizeof(int), 11);
int *p_num1 = half_search_rec(arr, arr+sizeof(arr)/sizeof(int), 32);
if(p_num) {
printf("找到的结果是 %d \n", *p_num);
}
else
printf("没有数字%d\n", *p_num);
if(p_num1) {
printf("找到的结果是 %d \n", *p_num1);
}
else
printf("没有数字%d\n", *p_num1);
return 0;
}