直接粗暴,就行循环。例如:
选择排序:利用循环每次选出最小的数依次放在序列最前面,时间复杂度为 O(n^2),具有不稳定性。
代码如下:
#include
using namespace std;
#define N 7
//选择排序(蛮力法,每次选出最小的放在最前面)
void selectSort(int a[]) {
for(int i=0;i<N-1;i++) {
int k = i;//临时存放最小值
for(int j=i+1;j<N;j++) {
if(a[k]>a[j]) {
k = j;
}
}
int t = a[i];//将最小值放在 i 的位置
a[i] = a[k];//即交换a[i] 和 a[j] 的值
a[k] = t;
}
}
int main() {
int a[] = {8,2,7,0,3,6,5};
selectSort(a);
for(int i=0;i<N;i++)
cout<<a[i]<<" ";
cout<<endl;
getchar();
return 0;
}
冒泡排序:利用循环依次比较相邻两个数的大小,每次将最大的数沉淀下来,即放在序列末尾。时间复杂度为 O(n^2),具有稳定性。
代码如下:
#include
using namespace std;
#define N 7
//冒泡排序(蛮力法,相邻两个数之间的比较,每次选出最大的数放在最后)
void bubbleSort(int a[]) {
for(int i=0;i<N;i++) {//外层循环,比较轮数
for(int 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;//交换,将最大的沉淀下来
}
}
}
}
int main() {
int a[] = {8,2,7,0,3,6,5};
bubbleSort(a);
for(int i=0;i<N;i++)
cout<<a[i]<<" ";
cout<<endl;
getchar();
return 0;
}
最大连续子序列问题:利用循环依次求前面所有数据从规定起点开始的和,若和为负,则令其为零,否则求最大连续子序列和。
#include
using namespace std;
#define R 6
//最大连续子序列问题
int maxsubSum(int a[]) {
int maxSum = 0;//最大连续子序列
int thisSum = 0;//本次求和
for(int i=0;i<R;i++) {
thisSum += a[i];
if(thisSum < 0)
thisSum = 0;
if(thisSum > maxSum)
maxSum = thisSum;//最大连续子序列
}
return maxSum;
}
int main() {
int a[] = {-2,11,-4,13,-5,-2};
cout<<"最大连续子序列为:"<<maxsubSum(a);
getchar();
return 0;
}
将一个问题拆分为相似的子问题,递归需要有出口,否则会陷入死循环,在遇到出口之前让反复执行这个程序即可。递归的空间复杂度大,是一个以空间换时间的算法,不适用于太过庞大的数据。
fibonacci 数列:fibonacci 数列是一个规律性很强的数列,从第三位数起,该数是前两个数的和,即:1,1,2,3,5,8,13……,递归性很强。
#include
using namespace std;
int fib(int n) {
if(n>2)
return fib(n-1) + fib(n-2);
else
return 1;//出口
}
int main() {
cout<<fib(1)<<" "<<fib(2)<<" "<<fib(3)<<" "<<fib(4);
cout<<" "<<fib(5)<<" "<<fib(6)<<" "<<fib(7)<<" "<<fib(8);
//1 1 2 3 5 8 13 21
getchar();
return 0;
}
排列问题:m 个数任取 n 个,不重复,m = n 时为全排列。不重复需要定义一个函数来确定,这个数据是否取过。
例如从5个数字中取5个,即 5 的全排列,我们都知道有120个,代码如下:
#include
using namespace std;
#define M 5//可选择的数字
#define N 5//取的数字
int num = 0;//记录个数
int res[N+1] = {0};//存放所取数字组合结果
//排列问题(m个数任取n个,不重复,m = n 时为全排列)
void output() {//输出函数
for(int i=1;i<=N;i++)
cout<<res[i]<<" ";
cout<<endl;
}
bool isIn(int a,int pos) {//判断是否选取过
for(int i=1;i<=pos;i++)
if(res[i] == a)
return true;
return false;
}
void Rank(int pos) {
if(pos>N) {
num++;
output();
return;//出口
}
for(int i=1;i<=M;i++) {
if(!(isIn(i,pos-1))) {//不在原序列中才取值
res[pos] = i;//取值
Rank(pos+1);//下一个
}
}
}
int main() {
Rank(1);
cout<<num<<endl;
getchar();
return 0;
}
分而治之,以某个元素为基准值分块儿,分别对两边进行处理。
快速排序:快排的关键是找到基准值,基准值的左边都是比它小的数,右边都是比它大的数。即是将比它小的数都移到它左边,比它大的数都移到右边。
#include
using namespace std;
#define N 9
//快速排序
int position(int a[],int start,int end) {
int i = start,j = end;
int tmp = a[start];//选第一个元素作为中间值
while(i!=j) {//未相遇时进行比较
while(i<j && a[j]>tmp)
//从右边开始寻找第一个比中间值小的元素
j--;
a[i] = a[j];
while(i<j && a[i]<=tmp)
//从左边开始寻找第一个比中间值大的元素
i++;
a[j] = a[i];
}
a[i] = tmp;//将中间值放回来
return i;
}
void quickSort(int a[],int start,int end) {
if(start<end) {//有多个元素时排序
int i = position(a,start,end);//基准元素
quickSort(a,start,i-1);//左边
quickSort(a,i+1,end);//右边
}
}
int main() {
int a[] = {4,2,11,0,7,8,5,21,9};
cout<<"原序列:"<<endl;
for(int i=0;i<N;i++)
cout<<a[i]<<" ";
cout<<endl;
quickSort(a,0,N-1);
cout<<"排序后:"<<endl;
for(int i=0;i<N;i++)
cout<<a[i]<<" ";
cout<<endl;
getchar();
return 0;
}
归并排序:先拆分,在合并,两者都是一个递归的过程。
#include
using namespace std;
#define N 9
//归并排序
void merge(int a[],int low,int mid,int high) {
//排序
int i = low,j = mid+1;//两个子序列的下标
//动态分配临时数组
int *tmp = (int*)malloc((high-low+1)*sizeof(int));
int k = 0;//临时数组的下标
while(i<=mid && j<=high) {
if(a[i]<a[j])
tmp[k++] = a[i++];
else
tmp[k++] = a[j++];
}
while(i<=mid)
tmp[k++] = a[i++];
while(j<=high)
tmp[k++] = a[j++];
for(i=low,k=0;i<=high;i++,k++)
a[i] = tmp[k];
free(tmp);//释放临时数组空间
}
void mergeSort(int a[],int start,int end) {
if(start<end) {//含多个元素进行排序
int mid = (start + end)/2;//分解
mergeSort(a,start,mid);//左边
mergeSort(a,mid+1,end);//右边
merge(a,start,mid,end);//有序数组的合并
}
}
int main() {
int a[] = {4,2,11,0,7,8,5,21,9};
cout<<"原序列:"<<endl;
for(int i=0;i<N;i++)
cout<<a[i]<<" ";
cout<<endl;
mergeSort(a,0,N-1);
cout<<"排序后:"<<endl;
for(int i=0;i<N;i++)
cout<<a[i]<<" ";
cout<<endl;
getchar();
return 0;
}
查找最大值和次大值问题:利用分治法解决即是拆分,每次找出基准值,分别找出基准值两边的最大值和次大值,该问题的出口是拆分到至多两个元素,即可依次往回求最大值和次大值。
#include
using namespace std;
#define N 9
//查找最大值和次大值问题
void maxsub(int a[],int start,int end,int *max1,int *max2) {
if(start == end) {//一个元素
*max1 = a[start];
*max2 = a[end];
}
else if((end-start)==1) {//两个元素
*max1 = a[start]>a[end]?a[start]:a[end];
*max2 = a[start]>a[end]?a[end]:a[start];
}
else {
int mid = (start+end)/2;
int lmax1,lmax2;
maxsub(a,start,mid,&lmax1,&lmax2);//左边
int rmax1,rmax2;
maxsub(a,mid+1,end,&rmax1,&rmax2);//右边
if(lmax1>rmax1) {
*max1 = lmax1;//最大值
*max2 = lmax2 > rmax1 ? lmax2 : rmax1;//次大值
}
else {
*max1 = rmax1;
*max2 = lmax1 > rmax2 ? lmax1 : rmax2;
}
}
}
int main() {
int a[] = {4,2,11,0,7,8,5,21,9};
cout<<"原序列:"<<endl;
for(int i=0;i<N;i++)
cout<<a[i]<<" ";
cout<<endl;
int max1,max2;
maxsub(a,0,N-1,&max1,&max2);
cout<<"最大值:"<<max1<<endl;
cout<<"次大值:"<<max2<<endl;
getchar();
return 0;
}
折半查找:建立在排序之后的基础上,在中间值的两边查找。这里用归并排序后的数据进行查找。
#include
using namespace std;
#define N 9
//折半查找
int binSearch(int a[],int start,int end,int x) {
if(start<=end) {
int mid = (start+end)/2;
if(a[mid] == x)//出口
return mid;
else if(a[mid]>x)//左边
return binSearch(a,start,mid-1,x);
else//右边
return binSearch(a,mid+1,end,x);
}
return -1;//未找到
}
int main() {
int a[] = {0,2,4,5,7,8,9,11,21};
cout<<binSearch(a,0,N-1,11)<<endl;
getchar();
return 0;
}