根据期末老师划的重点复习…=_=!
1 算法概念:
- 算法是解决问题的一种方法或一个过程,更严格的讲算法是由若干指令组成的又穷序列
2 算法特征:
- 输入:有0个或多个输入
- 输出:至少有1个输出
- 确定性:组成算法的指令必须清晰无歧义
- 有限性:每条指令执行的次数有限,时间也必须有限
3 分治法基本思想:
将一个规模为n的问题,分解为k个规模较小的子问题,这些子问题相互独立且与原问题相同。递归地解决这些子问题,然后将各个子问题的解合并得到原问题的解。
4 分治法基本步骤:
分治法在每一层递归上都有三个步骤:
- 分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题;
- 解决:若子问题规模较小而容易被解决则直接解,否则递归地解各个子问题;
- 合并:将各个子问题的解合并为原问题的解。
5 递归汉诺塔问题(递归):
- 算法思想:
利用递归的算法思想,
若n=1直接可以将a上的移动到b
若n>1的话按以下下步骤:
首先设法将a上的n-1个圆盘移动到c han(a—c---b)
然后将a上的最后一个圆盘移动到b move(a,b)
再次将c上的n-1照以上方式将圆盘移动到b han(c—b---a) - 时间复杂度:O(2^n)
- 代码
#include<iostream>
using namespace std;
int count=0;
void move(char a,char c){
cout<<a<<"---->"<<c<<endl;
count++;
}
//##########核心代码区域#############/
void hannuo(int n,char a,char b,char c){
if(n>0){
hannuo(n-1,a,c,b);
move(a,b);
hannuo(n-1,c,b,a);
}
}
int main(){
char a,b,c;
a = 'A';
b = 'B';
c = 'C';
hannuo(4,a,b,c);
cout<<"移动的步骤:"<<count<<endl;
return 0;
}
6 二分搜索算法(分治):
- 算法思想:
将n个元素分成个数大致相同的两半,取a[n/2]与x比较
如果找到,则终止
如果x<a[n/2] 则只在数组a的左半部继续搜索x
如果x>a[n/2] 则只在数组a的右半部继续搜索x - 算法时间:
最坏的时间:while循环执行O(logn)次 循环内执行O(1)次,整个算法时间是:O(logn) - 算法代码
#include<iostream>
using namespace std;
//数组,查找数x,数组的长度
int BinarySearch(int a[],int x,int n){
int left=0;
int right=n-1;
while(left<=right){
int mid = (left+right)/2;
if(x == a[mid]) return mid;
else if(x>a[mid]) left = mid+1;
else right = mid-1;
}
return -1;
}
int main(){
int a[8]={1,2,3,4,5,6,7,8};
int index;
index = BinarySearch(a,4,8);
cout<<"数组下标index="<<index<<endl;
return 0;
}
7 合并排序和快速排序算法(分治):
- 算法思想:
合并排序的思想:将待排序的元素分成大小大致相同的两个子集和,分别对两个子集排序,最终将排序好的子集合并成要求的排好序的集合
快速排序的思想:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。: - 算法时间:
合并排序:O(nlogn)
快速排序:
最坏情况:O(n^2)
最好情况:O(nlogn)
平均时间复杂度:O(nlogn) - 算法代码:
//合并排序//
//合并排序//
#include<iostream>
using namespace std;
void MergeSort(int a[],int left,int right,int c[]);
void Merge(int left,int mid,int right,int c[],int a[]);
int main(){
int a[10] = {1,3,5,6,4,2,7,9,8,0};
int c[10] = {0};
MergeSort(a,0,10,c);
for(int i=0;i<10;i++){
cout<<a[i]<<",";
}
return 0;
}
void MergeSort(int a[],int left,int right,int c[]){
if(left<right){
int mid=(left+right)/2;
MergeSort(a,left,mid,c); //左边合并排序
MergeSort(a,mid+1,right,c);//右边合并排序
Merge(left,mid,right,c,a); //将排序好的子集合并到数组b
}
}
void Merge(int left,int mid,int right,int c[],int a[]){
int i = left; //左序列指针
int j = mid+1; //右序列指针
int t = 0; // c数组指针
while(i<=mid && j<=right){
if(a[i]<=a[j]){
c[t++] = a[i++];
}
else{
c[t++] = a[j++];
}
}
while(i<=mid) c[t++] = a[i++]; //将左边剩余元素填充进c中
while(j<=right) c[t++] = a[j++]; //将右边剩余元素填充进c中
t = 0;
//将c中元素拷贝到a中
while(left<=right) a[left++]=c[t++];
}
//快速排序//
//快速排序//
#include<iostream>
using namespace std;
void quickSort(int a[],int left,int right){
int i = left;
int j = right;
int t=0;
if(i<j){ //待排序的元素至少有两个的情况
t = a[i]; //待排序的第一个元素作为基准元素
while(i != j){ //从左右两边交替扫描,直到i = j
while(j>i && a[j]>=t)
j--; //从右往左扫描,找到第一个比基准元素小的元素
a[i] = a[j];//找到这种元素a[j]后与a[i]交换
while(i<j && a[i]<=t)
i++; //从左往右扫描,找到第一个比基准元素大的元素
a[j] = a[i];//找到这种元素arr[left]后,与arr[right]交换
}
a[j] = t; //基准元素归位
quickSort(a,left,i-1); //对基准元素左边的元素进行递归排序
quickSort(a,j+1,right); //对基准元素右边的元素进行递归排序
}
}
int main(){
int a[10] = {1,3,5,6,4,2,7,9,8,0};
quickSort(a,0,9); //传递的长度是n-1
for(int i=0;i<10;i++){
cout<<a[i]<<",";
}
return 0;
}