acm常见的输入输出类型
1.没有输入时结束
int a,b;
while(scanf("%d %d",&a,&b)!=EOF){
…程序体
}
2.给定样例个数
int n;
scanf("%d",&n);
while(n–){
…程序体
}
3.为0时结束输入
int a,b;
while(scanf("%d %d",&a,&b)&&(a||b)){
…程序体
}
复杂度分析
O(f(n)) 为算法f(n)的渐进时间复杂度,简称时间复杂度。一般情况下我们分析一个算法是否可行我们就分析算法的渐进时间复杂度
常见的算法时间复杂度由小到大依次为:
Ο(1)<Ο(log2n)<Ο(n)<Ο(nlog2n)<Ο(n^2)<Ο(n ^3) <…<Ο(2^n)<Ο(n!)(其中O(1)又称作是线性时间复杂度)
求和法则:是指若算法的2个部分时间复杂度分别为 T1(n)=O(f(n))和 T2(n)=O(g(n)),则 T1(n)+T2(n)=O(max(f(n), g(n)))
特别地,若T1(m)=O(f(m)), T2(n)=O(g(n)),则 T1(m)+T2(n)=O(f(m) + g(n))
(1).对于一些简单的输入输出语句或赋值语句,近似认为需要O(1)时间
(2).对于顺序结构,需要依次执行一系列语句所用的时间可采用大O下"求和法则"
乘法法则: 是指若算法的2个部分时间复杂度分别为 T1(n)=O(f(n))和 T2(n)=O(g(n)),则 T1*T2=O(f(n)*g(n))
对于循环结构,循环语句的运行时间主要体现在多次迭代中执行循环体以及检验循环条件的时间耗费,一般可用大O下"乘法法则"
另外还有以下2个运算法则:(1) 若g(n)=O(f(n)),则O(f(n))+ O(g(n))= O(f(n));(2) O(Cf(n)) = O(f(n)),其中C是一个正常数
排序
冒泡排序
基本思想:通过对相邻元素的比较和交换,使全部记录排列有序
过程:对每两个相邻元素进行比较,若为逆序,则将两者交换,这样的操作反复进行,直至全部记录都比较,交换完毕。如此经过一趟冒泡排序之后,就将关键字最大(或最小)的元素安排在最后一个元素的位置上。然后对n-1个元素做同样的操作。
void Babble_Sort1(int *array, int length) {
for(int i = 0; i < length - 1; i ++)
for(int j = 0; j < length - 1 - i; j ++)
if(array[j] > array[j + 1]) {
int t = array[j];
array[j] = array[j + 1];
array[j + 1] = t;
}
}
选择排序
将数组分为无序和有序两个部分,起初视数组都为无序,每次让数组无序部分的第一个元素作为擂主,让其后的元素开始打擂,每次打至数组的最后一个元素,如果擂主变了(后续数组中存在比擂主小的元素),则将擂主归并作为有序部分的最后一个元素并按照上述规则继续打擂,直至数组的最后一个元素。
void Seletion_Sort(int *array, int length) {
int index;
for(int i = 0; i < length - 1; i ++) {
index = i;
for(int j = i + 1; j < length; j ++)
if(array[j] > array[index])
index = j;
if(index != i)
swap(array[index], array[i]);
}
插入排序
基本思想:从数组的第二个单元开始,依次从原始数据中取出数据,并将其插入到数组中该单元之前的已排好序的序列中的合适的位置处
void Insertion_Sort(int *array, int length) {
int i, j;
int Tmp;
for(i = 1; i < length; i ++) {
Tmp = array[i];
for(j = i; j > 0 && array[j-1] > Tmp; j --)
array[j] = array[j-1]; //后移元素
array[j] = Tmp; //插入
}