以下介绍常用算法的原理以及主要相关代码实例。
1.冒泡排序算法
冒泡排序算法的思想对于两两相邻的元素进行比较,不合适就交换位置,重复上述步骤知道没有元素可交互位置,此时说明已经排好了顺序。
以下为冒泡排序的实现,冒泡排序的特点如下:
// 分类 -------------- 内部比较排序 // 数据结构 ---------- 数组 // 最差时间复杂度 ---- O(n^2) // 最优时间复杂度 ---- 如果能在内部循环第一次运行时,使用一个旗标来表示有无需要交换的可能,可以把最优时间复杂度降低到O(n) // 平均时间复杂度 ---- O(n^2) // 所需辅助空间 ------ O(1) // 稳定性 ------------ 稳定
实例:
void swap(int a[],int n){
int i,j;
for(i = 0;i < n -1;++i){
for(j =0;j < n - 1 - i;++j){ //每次元素需要比较的次数
if(a[j] > a[j + 1]){
int t = a[j];
a[j] = a[j + 1];
a[j + 1] = t;
}
}
}
}
2.冒泡排序的改进,双重冒泡过程。
排序思想,为这中排序,将大的数据往后面冒泡,将小的数据往前面排序,直到排完为止。
#include <stdio.h>
int main(void){
int a[5] = {3,1,10,9,8};
int i,j;
int l = 0;
int r = 5 -1;
while(l < r){
for(i =l;i<r;++i){
if(a[i] > a[i + 1]){
int t = a[i];
a[i] = a[i + 1];
a[i+ 1] = t;
}
}
r--;
for(i = r;i >l;--i){
if(a[i - 1] > a[i]){
int t = a[i];
a[i] = a[i - 1];
a[i - 1] = t;
}
}
l++;
}
for(i = 0;i< 5;++i){
printf("%d\n",a[i]);
}
return 0;
}
3,选择排序
选择排序的思想是找到一个最小的元素,之后在后续的元素中继续找进行查找和当前最小的元素进行比较如果找到,则将记录其元素,查找完之后,在于已经排序的元素位置进行数据交换即可。
#include <stdio.h>
int main(void){
int a[5] = {3,1,10,9,8};
int i,j;
for(i = 0;i <5;++i){
int m = i;
for(j = i;j < 5;++j){ //找到比先前更小的元素的位置
if(a[j] < a[m]){
m = j;
}
}
if(m != i){
int t = a[m];
a[m] = a[i];
a[i] = t;
}
}
for(i = 0;i< 5;++i){
printf("%d\n",a[i]);
}
}
4.插入排序
排序算法排序方法步骤思想
1,从第一个元素开始,该元素可以认为已经被排序
2,取出下一个元素,在已经排序的元素序列中从后向前扫描
3,如果该元素(已排序)大于新元素,将该元素移到下一位置
4,重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
5,将新元素插入到该位置后
重复步骤2~5
#include <stdio.h>
int main(void){
int a[5] = {3,1,10,9,8};
int i,j;
for(i = 1;i < 5 ;++i){
int t = a[i];
j = i - 1; //此处的循环从当前元素的前一个元素开始循环比较
while(j >= 0 && t < a[j]){
a[j + 1] = a[j];
j--;
}
a[j+1] = t;
}
for(i = 0;i< 5;++i){
printf("%d\n",a[i]);
}
}
5.二分插入排序
#include <stdio.h>
int main(void){
int a[5] = {4,1,5,3,6};
int i,j;
for(i = 1;i < 5;++i){
int t = a[i];
int l = 0;
int r = i - 1;
while(l <= r){
int mid = (l + r)/2;
if(a[mid] > t){
r = mid - 1;
}else{
l = mid + 1;
}
}
for(j = i - 1;j >= l;j--){
a[j+ 1] = a[j];
}
a[l] = t;
}
for(i = 0;i< 5;++i){
printf("%d\n",a[i]);
}
return 0;
}
6.归并排序
该排序是一种将事件拆分成若干份小模块来进行处理,之后再将所有的小模块结合起来处理以此来解决最终大问题。
归并排序需要额外分配空间,拥有存储已经就解决好的模块。
//归并排序递归过程
void merger(int a,int l,int mid,int r){
//当前空间的长度
int len = r - l + 1;
int *temp = new int[len];
int i =l;
int j = mid + 1;
int t = 0;
//比较两个空间的元素并插入至辅助空间中
while(i<= mid && j < r){
temp[t++] = a[i] < a[j] ?:a[i++],a[j++];
}
//两个数组的长度可能长度不一致,将剩余的数据也放入至辅助空间中
while(i <= mid){
temp[t++] = a[i++];
}
while(j <= r){
temp[t++] = a[j++];
}
//再将辅助空间中的元素存放回原始数组中,从左边界开始存放
int m;
for(m = 0;m < len;++m){
a[l++] = temp[m];
}
}
void mer(int a[],int l,int r){
if(l == r){
return ;
}
int mid = (l + r)/2;
//left 不断拆分
mer(a,l,mid - 1);
//rigth 不断拆分
mer(a,mid + 1,r);
//将拆分的单元进行合并处理
merger(a,l,mid,r);
}
//非递归过程,其思想是进行2分,4分,8分以此类推,直到不能区分为止
相当于每次进行数据划分,每次从左边界往右边成2的倍数扩大数据划分,之后确定中间值,和有边界值,在进行一次归并排序即可。
void nomer(int a[],int len){
int l,r,mid;
int i;
//每次进行2的倍数区分
for(i = 1;i < len;i *= 2){
l = 0;
//进行数据分区空
while(l + i < len){
mid = (l + i - 1)/2; //确定分区中间值
r = mid + i < len ?:mid + i,len - 1; //驱动右分区边界
//进行归并排序
merger(a,l,mid,r);
l = r + 1;
}
}
}
7.快速排序
//快速排序的思想是确认一个元素为基准,之后从两边今次那个比较,按照升序为例,比基准小的放置左边,比基准大的放置右边。
//递归方式
void quick(int a[],int l,int r){
int i,j;
i = l;
j = r;
int t = a[l]; //选取一个基准
while(i < j){
//<---从右边,将小于基准的放置数组左边
while(i < j && a[j] > t){
j--;
}
if(i < j){
a[i++] = a[j];
}
//-->将大于基准的放置数组的右边
while(i < j && a[i] < t){
i++;
}
if(i < j){
a[j--] = a[i];
}
}
a[i] = t; //最后将这个基准填入到最后的坑中
quick(a,l,i - 1);
quick(a,i + 1,r);
}
//非递归
void qort(int a[],int l,int r){
int i,j;
i = l;
j = r;
int t = a[l]; //选取一个基准
while(i < j){
//<---从右边,将小于基准的放置数组左边
while(i < j && a[j] > t){
j--;
}
if(i < j){
a[i++] = a[j];
}
//-->将大于基准的放置数组的右边
while(i < j && a[i] < t){
i++;
}
if(i < j){
a[j--] = a[i];
}
}
a[i] = t; //最后将这个基准填入到最后的坑中
return i;
}
void noquick(int a[],int len,int l,int r){
stack<int> sk;
int i = l;
int j = r;
if(i < j){
//将起始位置和终止位置压入栈中
//先进行一次快速排序
int mid = qort(a,i,j);
//将区间位置压入栈中(左区间)
if(i < mid - 1){
sk.push(i);
sk.push(mid - 1);
}
//将右区间压入栈中
if(mid + 1 <j){
sk.push(mid + 1);
sk.push(j);
}
//进行排序
while(!sk.empty()){
int ll = sk.top();
sk.pop();
int rr = sk.top();
sk.pop();
mid = qort(a,ll,rr);//进行排序
if(ll < mid - 1){
sk.push(ll);
sk.push(mid - 1);
}
if(mid + 1 < rr){
sk.push(mid + 1);
sk.push(rr);
}
}
}
}