第十四届蓝桥杯临考备赛(临阵磨枪了啊!!难受难受)

文章回顾了C语言的基本数据类型、库函数,特别是qsort和bsearch的使用,并介绍了C++中的STL,如vector、set和map的常见操作,强调了它们在编程竞赛如蓝桥杯中的应用。
摘要由CSDN通过智能技术生成

一、有关语法的回顾

我报的是C/C++大学生B组的,但是碍于先前C语言的基础比较薄弱,所以花了近一周的时间来回顾C,然后才开始练习做题。废话不多说,直接进入正题。

1.C语言基本数据类型及其范围

蓝桥杯中最常用的是int(在2*10^9左右),还有便是longlong(9*10^19左右)。结构体和指针倒是几乎用不到,虽然当时还花了不少时间去学那些玩意儿...(算了,学到就是赚到,我不该这么目光短浅)

2.必备C语言库函数

C中的库函数相较于C++还真是相形见绌,少得可怜啊啊...但是其中有两个极其重要的函数必须掌握:

1)qsort(数组起始地址,数组长度,数组元素大小,比较函数);

------》这个就是快速排序函数,时间复杂度是n*logn,不稳定,算是一种很好用的库函数了。在使用过程中,要自己去写比较函数cmp,这样做的目的是使得该函数不仅可以对基本数据类型的数组排序,还可以对用户自定义的数据类型排序,这也是用户需要自己写比较函数的意义所在。

------》比较函数书写需要值得提及的是:该函数形参是两个无类型常量指针,即const void *;并且返回的形参必须是int类型,大于0表示A>B,等于0表示A=B,小于0表示A<B;在函数内部进行比较时,需注意不同数据类型的比较方式,其具体步骤可归结为:先将两个无类型常量指针强制转换为目标数据类型指针,然后两者先解引用再作差,返回差值即可;但是double类型的数据在比较时因为精度缺失,不能单纯地作差来判别,需要去定义一个极小值(1e-8)作为指标,两者差值大于等于该指标,即说明A>B/A=B,两者差值小于-(指标),说明A<B。详情可参考下图:

2)bsearch(待查元素的地址,数组起始地址,数组长度,数组元素大小,比较函数);

------》这就是比较高效且简单的二分查找算法,使用前必须保证数组是有序的,时间复杂度是logn,函数比较简单,使用方法和上诉的qsort差不多,只不过要查找的元素必须先用一个变量存一下,然后将这个变量的地址传给bsaerch,bsearch的返回值是个指针,要想获取到待查元素的下标,只需用该地址减去数组首地址即可(获取地址时不要忘了强转!)。详情可见下图:

3)自己亲手实现代码:

void my_qsort(int *arr,int low,int high) {
	if(low<high){//边界条件 
		int i = low,j = high,flag = arr[low];//将最左边元素作为flag 
		while(i<j){//左指针小于右指针 
			while(i<j&&arr[i]<flag){//并且左边的元素比flag小 
				i++;//左指针自增 
			}//循环结束时遇到左边元素比flag大/相等 
			if(i<j){//左指针小于右指针 
				arr[j--]=arr[i];//把这个元素赋值给右指针(比flag大的该放到右边) 右指针减一 
			}
			while(i<j&&arr[j]>flag){//右边的元素都比flag大 
				j--;//右指针减1 
			}
			if(i<j){//右边元素比flag小 
				arr[i++]=arr[j];//右边元素放到左边去  左指针移动 
			}
		}
		arr[i] = flag;//此时i=j,将flag插回数组中 
		my_qsort(arr,low,j-1);//排左边 
		my_qsort(arr,i+1,high);//排右边 
	}
}
int my_bsearch(int* arr,int len,int target){
	int low = 0,high = len-1;//左右边界
	while(low<=high){
		int mid = (low+high)/2;
		if(arr[mid]<target){
			low = mid+1;
		}else if(arr[mid]>target){
			high = mid-1;
		}else{
			return mid;
		}
	} 
}

 3.C++中必备的STL中的工具类:

1)最最最重要的就是vector了!!!这就是C语言数组的加强版!

在使用vector之前,需要引入头文件<vector>,其他类似的容器也是如此,使用前都需要先引入头文件,这是因为C++中的工具类较C语言多得多,因此得单独引入各个头文件。言归正传,C++中的vector在蓝桥杯中也就用到几个基本操作,比如创建及初始化,在数组尾部插入和删除元素,遍历该动态数组,修改数组中元素的值(和数组的用法一样)。

#include<algorithm>
#include<cstdio>
#include<vector>

using namespace std;

int main1(){
	vector<double> v1(10);//定义了一个double类型的动态数组 初始化大小为10 默认值0.0
	//1. 插入和删除末尾元素
	v1.push_back(3.14159);
	v1.pop_back();
	//2.insert();
	   //1)指定位置插入元素
	v1.insert(v1.begin()+3,23333.333); 
	v1.insert(v1.begin()+1,(1.11,2.22,3.33));
	for(int i=0;i<v1.size();i++){
		printf("%.2lf\n",v1[i]);
	} 
	return 0;
}

int main(){
	int n;
	scanf("%d",&n);
	vector<int> a[n];
	a[0].push_back(1);
	for(int i=2;i<=n;i++){
		a[i-1].push_back(1);
		for(int j=1;j<=2*i-3;j++){
			a[i-1].push_back(i);
		}
		a[i-1].push_back(1);
	}
	for(int i=0;i<n;i++){
		for(int k=1;k<n-i;k++){
			printf("  ");
		}
		for(int j=0;j<a[i].size();j++){
			printf("%d ",a[i][j]);
		}
		printf("\n");
	}
	return 0;
}

2)其次就是set集合,最主要的功能是可以自动去重,并且还会按字典序升序进行怕排序。之前做的真题有一道就是求直线个数的,但要求去重,然后自己如果去判断重很麻烦,而直接将那个直线结构体变量存到set里面之后再直接计算出set的长度就方便多啦!!!详情见以下代码:

#include<algorithm>
#include<cstdio>
#include<set>
#include<iterator>
#include<cmath>

using namespace std;

struct Line{
	double k;
	double b;
	Line(){
	}
	Line(double _k,double _b){
		k = _k;
		b = _b;
	}
}line[10];

bool operator <(const Line& l1,const Line& l2){
	if(l1.k<l2.k){
		return true;
	}else{
		if(l1.b<l2.b){
			return true;
		}
		return false;
	}
}

int main(){
	set<int> a;
	a.insert(1);
	a.insert(2);
	a.insert(3);
	a.insert(1);
	printf("%d\n",a.size());
	for(set<int>::iterator it = a.begin();it!=a.end();it++){
		printf("%d ",*it);
	}
	set<Line> b;
	for(int i=0;i<10;i++){
		line[i].k = 10-i;
		line[i].b = i+10;
		b.insert(line[i]);
	}
	for(set<Line>::iterator it = b.begin();it!=b.end();it++){
		printf("k=%.2lf,b=%.2lf\n",it->k,it->b);
	}
	
	Line l1(1,2);
	b.insert(l1);
	printf("\n%d",b.count(l1));
	b.erase(l1);
	printf("\n%d",b.count(l1));
	return 0;
}

顺带一提,set遍历不同于vector,vector遍历时可以引用数组下标,而set不行,必须使用迭代器iterator,类似于C中的指针,因此也可直接通过it这个迭代器变量来访问set集合中的元素;此外,如果是自定义类型的变量放入set集合中,一定不要忘记运算符的重载,也就有点像之前快排中需要自己写比较函数的感觉,但是这个重载函数的形参是引用类型的结构体常量,引用这个东西算是C++中特有的,C里面是没法使用的。

3)map,也是有用的,虽然可能用不到,但是它的int和string类型的对应这一功能有时却是很管用,还是了解一下的吧,详情见代码:

#include<algorithm>
#include<cstdio>
#include<cmath>
#include<iterator>
#include<map>

using namespace std;

int main(){
	//1.map的定义和初始化  初始化有三种 和数组初始化差不多的感觉 
		//需要注意的可能就是pair来初始化 
	map<int,string> map1;
	map<int,string> map2=
	{{11,"孙长青"},{1,"靖刘剑"},{8,"高源"}};
	map<int,string> map3=
	{pair<int,string>(23,"SCT"),pair<int,string>(48,"Hello")}; 
	map2.insert({233,"哈哈哈"}); 
	map2[233] = "我亲爱你";//修改键值对 
	auto iter = map2.find(233);//根据键寻找值  如果没找到返回map2.end() 是一个指针 
	printf("%s\n",iter->second.c_str());
	printf("%s\n",map2[11].c_str());//这边有将C++中的string用C语言的%s输出的转化,即c_str() 
	map2.erase(233);//删除键值对 
	for(auto it=map2.begin();it!=map2.end();it++){//遍历该map  可以使用auto关键字自适应迭代器 
		printf("key=%02d,value=%s\n",it->first,it->second.c_str());
	} 
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值