一、算法的相关概念
程序 = 数据结构 + 算法
算法是程序设计的灵魂,结构是程序设计的肉体
算法:计算机解决问题的方法或步骤
1.1 算法的特性
1> 确定性:算法中每一条语句都有确定的含义,不能模棱两可
2> 有穷性:程序执行一段时间后会自动结束
3> 输入:至少有零个或多个输入
4> 输出:至少一个或多个输出
5> 可行性:经济可行性、社会可行性、能够运行
1.2 算法的设计要求
1> 正确性:给定合理的输入数据,能够得到正确的结果
2> 健壮性:对于给定的不合理的输入数据,能够给出相应的处理措施
3> 可读性:程序核心代码写注释、程序代码有缩进、程序代码命名规范
4> 高效率:要求时间复杂度要尽可能低
5> 低存储:要求空间复杂度尽可能低
1.3 时间复杂度
1> 算法时间复杂度计算公式:T(n) = O(f(n));
T(n):时间复杂度
n:表示问题的规模
f(n) :是问题规模与执行次数之间的函数
O(f(n)):使用O阶记法,记录算法时间复杂度
2> 时间复杂度推导
3> 常见的时间复杂度
二、排序算法
根据数据元素的关键字,安照升序或降序的方式将数据元素重新排列的过程称为排序
2.1 排序的分类
1> 交换类排序:冒泡排序、快速排序
2> 选择类排序:简单选择排序、堆排序
3> 插入类排序:直接插入排序、折半插入排序
4> 归并排序:二路归并、多路归并
2.2 冒泡排序(O(N^2))
1> 在排序过程中,越大(小)的数据,经由交换后,会慢慢的“浮”到顶端,如同气泡一样
2> 冒泡排序原理
比较相邻元素,如果第一个比第二个大(小)则交换
经过一趟排序后会使最大(最小)的元素落到最后 重复上面的步骤,直到没有任何一对数字需要比较为止
当某一趟的排序过程中,出现没有数据交换的过程,则结束整个排序
//定义冒泡排序函数
void bubble_sort(int *arr, int n)
{
for(int i=1; i<n; i++) //趟数
{
int flag = 0; //判断是否在排序中改变
for(int j=0; j<n-i; j++)
{
if(arr[j] > arr[j+1])
{
flag = 1; //设置标志
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
//说明上一堂的排序中,没有进行数据的交换
if(flag == 0)
{
break;
}
}
printf("排序成功\n");
}
2.3 选择排序
1> 概念:每次从待排序序列中,找到最大(小)值,将其与待排序序列的第一个进行交换
2> 原理
1、从待排序序列中选择最值
2、如果最值不是待排序序列的第一个,则进行交换
3、从剩余待排序序列中,继续重复前两次的操作,直到,待排序序列为空
3> 算法
//定义选择排序
void select_sort(int *arr, int n)
{
int mini = 0;
for(int i=0; i<n; i++) //遍历已排序序列
{
mini = i; //将待排序的第一个元素当做最值
for(int j=i+1; j<n; j++) //遍历待排序序列
{
if(arr[mini] > arr[j])
{
mini = j; //更新最小值下标
}
}
//判断最小值是否是第一个元素
if(mini != i)
{
//将最小值与待排序序列第一个交换
int temp = arr[mini];
arr[mini] = arr[i];
arr[i] = temp;
}
}
printf("排序结果\n");
}
2.4 直接插入排序
1> 每次从待排序序列中,选择第一个,将其插入到已排序序列中
2> 原理
1、选取待排序序列中的第一个元素
2、跟前面的元素依次比较,如果前面的比当前元素大(小),则将前面的元素后移一位
3、直到出现前面的不比当前的大(小)或者已经到最前面了,将选取的元素,放入空位置上
4、对于待排序序列中的所有元素,重复上述操作
3> 代码
//定义插入排序函数
void insert_sort(int *arr, int n)
{
int i,j;
for(i=1; i<n; i++) //不断从待排序序列中选元素
{
int temp = arr[i]; //将待排序序列的第一个备份
for(j=i-1; temp<=arr[j]&&j>=0; j--)
{
//将元素后移
arr[j+1] = arr[j];
}
arr[j+1] = temp; //将元素放入对应位置
}
printf("排序成功\n");
}
2.5 快速排序(O(n*log2n))
1> 概念:快速排序是在序列元素与选定基准元素比较分割为大小两部分的交换排序
2> 原理
从待排序列中任取一个基准元素
与基准元素比较将待排序列分割为大小两部分
再对各部分重新选择基准元素并依此规则排序
直到每个部分只剩一个元素为止
3> 算法
//定义一趟快速排序函数
//返回值:基准最终的下标
//arr:数组起始地址
//low:要排序容器的最小下标
//high:要排序容器的最大下标
int part(int *arr, int low, int high)
{
//选中基准
int X = arr[low]; //把第一个元素当做基准
while(high > low) //让循环继续的条件
{
//判断high所在的元素是否都比基准大
while(arr[high] >= X && high>low) //为了不错位
{
high--;
}
arr[low] = arr[high]; //将小的值,向前放
//判断low所在的元素是否都比基准小
while(arr[low] <= X && high>low)
{
low++;
}
arr[high] = arr[low]; //将大的值,向后放
}
//基准的位置就选出来了 此时 high==low
arr[low] = X; //将基准放入指定位置
printf("排序一趟\n");
return low; //返回基准的下标
}
//定义快速排序函数
void quick_sort(int *arr, int low, int high)
{
if(low>=high)
{
return; //只有一个元素,无需排序。递归出口
}
//不只一个元素时
int mid = part(arr, low, high); //进行一趟排序
//对左半部分快排
quick_sort(arr, low, mid-1);
//对右半部分快排
quick_sort(arr, mid+1, high);
}