算法基础知识——排序与查找

算法基础知识——排序与查找

目录:

  1. 基础知识
    1. 排序(基本类型、结构体或类)
    2. 查找(线性查找、二分查找)
  2. 应用实例
    1. 排序【华中科技大学】
    2. 成绩排序【清华大学】
    3. 成绩排序2【清华大学】
    4. 特殊排序【华中科技大学】
    5. 整数奇偶排序【北京大学】
    6. 小白鼠排队【北京大学】
    7. 奥运拍讯问题【浙江大学】
    8. 找x【浙江大学】
    9. 查找【北京邮电大学】
    10. 找最小数【北京邮电大学】
    11. 打印极值点下标【北京大学】
    12. 找位置【华中科技大学】

一、基础知识

1、排序

  • 基本类型的排序:对整型、浮点型等计算机编程语言内置的基本类型进行排序
  • 结构体或类的自定义排序:
    • 方法一:设计比较函数
    • 方法二:在结构体或类的内部重载小于号

2、查找

  • 先通过排序,方便查找。
  • 查找的基本要素:
    • 查找空间(解空间):在查找空间中找寻复合要求的解。
    • 查找目标:需要一个目标来判断查找空间中的各个元素是否符合要求,以便判断查找活动是否成功。
    • 查找方法:利用某种特定的策略在查找空间中查找各个元素。
  • 常用查找方法:
    • 线性查找:多次(m次)查找时间复杂度:O(mn)
    • 二分查找:多次(m次)查找时间复杂福:O(nlogn + mlogn)
    • 当m达到一定程度时,二分查找的性能远优于线性查找。

二、应用实例

1、题目描述:对输入的n个数进行排序并输出。【华中科技大学】

  • 输入格式:输入的第一行包括一个整数n(1<=n<=100)。接下来的一行包括n个整数。
  • 输出格式:可能有多组测试数据,对于每组数据,将排序后的n个整数输出,每个数后面都有一个空格。每组测试数据的结果占一行。
  • 样例输入:
    • 4
    • 1 4 3 2
  • 样例输出:
    • 1 2 3 4 

示例代码:

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;
vector<int> myVector;

int main(){
	int n, input;
	while(cin >> n){
		for(int i = 0; i < n; i++){
			cin >> input;
			myVector.push_back(input);
		}
		sort(myVector.begin(), myVector.end());
		for(vector<int>::iterator iter = myVector.begin(); iter != myVector.end(); iter++){
			cout << *iter << " ";
		}
		cout << endl;
		myVector.clear();
	}
	return 0;
}

2、题目描述:用一维数组存储学号和成绩,然后,按成绩排序输出。【清华大学】

  • 输入格式:输入第一行包括一个整数N(1<=N<=100),代表学生的个数。接下来的N行每行包括两个整数p和q,分别代表每个学生的学号和成绩。
  • 输出格式:按照学生的成绩从小到大进行排序,并将排序后的学生信息打印出来。如果学生的成绩相同,则按照学号的大小进行从小到大排序。
  • 样例输入:
    • 3
    • 1 90
    • 2 87
    • 3 92
  • 样例输出:
    • 2 87
    • 1 90
    • 3 92

示例代码:

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

struct Student{
	int number;
	int score;
	Student(int n, int s):number(n), score(s){};
	bool operator<(const Student &stu);
};

vector<Student> stuVector;

bool Student::operator<(const Student &stu){
	if(score < stu.score){
		return true;
	}else if(score == stu.score){
		return number < stu.number;
	}else{
		return false;
	}
}

int main(){
	int n, number, score;
	while(cin >> n){
		for(int i = 0; i < n; i++){
			cin >> number >> score;
			Student stu(number, score);
			stuVector.push_back(stu);
		}
		sort(stuVector.begin(), stuVector.end());
		for(vector<Student>::iterator iter = stuVector.begin(); iter != stuVector.end(); iter++){
			cout << (*iter).number << " " << iter->score << endl;
		}
		stuVector.clear();
	}
	return 0;
}

3、题目描述:输入任意(用户,成绩)序列,可以获得成绩从高到低或从低到高的排列,相同成绩都按先录入排列在前的规则处理。【清华大学】

  • 输入格式:输入多行,先输入要排序的人的个数,然后输入排序方法0(降序)或者1(升序)再分别输入他们的名字和成绩,以一个空格隔开
  • 输出格式:按照指定方式输出名字和成绩,名字和成绩之间以一个空格隔开
  • 样例输入:
    • 3
    • 0
    • fang 90
    • yang 50
    • ning 70
  • 样例输出:
    • fang 90
    • ning 70
    • yang 50

示例代码:

#include <iostream>
#include <string>
#include <algorithm>
#include <vector>

using namespace std;

struct Student{
	string name;
	int score;
	int order;
	Student(string n, int s, int o):name(n), score(s), order(o){};
};

vector<Student> stuVector;

bool CompareAsc(const Student &stuA, const Student &stuB){
	if(stuA.score != stuB.score){
		return stuA.score < stuB.score;
	}else{
		return stuA.order < stuB.order;
	}
}

bool CompareDesc(const Student &stuA, const Student &stuB){
	if(stuA.score != stuB.score){
		return stuA.score > stuB.score;
	}else{
		return stuA.order < stuB.order;
	}
}

int main(){
	int number, orderStyle, score;
	string name;
	while(cin >> number){
		cin >> orderStyle;
		int count = 0;
		for(int i = 0; i < number; i++){
			cin >> name >> score;
			count++;
			Student stu(name, score, count);
			stuVector.push_back(stu);
		}
		if(orderStyle == 0){
			sort(stuVector.begin(), stuVector.end(), CompareDesc);
		}else{
			sort(stuVector.begin(), stuVector.end(), CompareAsc);
		}
		for(vector<Student>::iterator iter = stuVector.begin(); iter != stuVector.end(); iter++){
			cout << iter->name << " " << iter->score << endl;
		}
		stuVector.clear();
	}
	return 0;
}

4、题目描述:输入一系列整数,将其中最大的数挑出(如果有多个,则挑出一个即可),并将剩下的数进行排序,如果无剩余的数,则输出-1。【华中科技大学】

  • 输入格式:输入第一行包括1个整数N,1<=N<=1000,代表输入数据的个数。接下来的一行有N个整数。
  • 输出格式:可能有多组测试数据,对于每组数据,第一行输出一个整数,代表N个整数中的最大值,并将此值从数组中去除,将剩下的数进行排序。第二行将排序的结果输出。
  • 样例输入:
    • 4
    • 1 3 4 2
  • 样例输出:
    • 4
    • 1 2 3

示例代码:

#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

vector<int> myVector;

int main(){
	int n, inputNumber;
	while(cin >> n){
		if(n == 1){
			cin >> inputNumber;
			cout << inputNumber << endl << -1 << endl;
		}else{
			for(int i = 0; i < n; i++){
				cin >> inputNumber;
				myVector.push_back(inputNumber);
			}
			sort(myVector.begin(), myVector.end());
			cout << myVector.back() << endl;
			for(vector<int>::iterator iter = myVector.begin(); iter != myVector.end() - 1; iter++){
				cout << *iter << " ";
			}
			cout << endl;
			myVector.clear();
		}
	}
	return 0;
}

5、题目描述:输入10个整数,彼此以空格分隔。重新排序以后输出(也按空格分隔),要求: 1.先输出其中的奇数,并按从大到小排列; 2.然后输出其中的偶数,并按从小到大排列。【北京大学】

  • 输入格式:任意排序的10个整数(0~100),彼此以空格分隔。
  • 输出格式:可能有多组测试数据,对于每组数据,按照要求排序后输出,由空格分隔。1. 测试数据可能有很多组,请使用while(cin>>a[0]>>a[1]>>...>>a[9])类似的做法来实现;2. 输入数据随机,有可能相等。
  • 样例输入:
    • 4 7 3 13 11 12 0 47 34 98
  • 样例输出:
    • 47 13 11 7 3 0 4 12 34 98

示例代码:

#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

vector<int> oddVector;
vector<int> evenVector;

bool CompareAsc(const int &a, const int &b){
	return a < b;
}

bool CompareDesc(const int &a, const int &b){
	return a > b;
}

void Print(vector<int> v){
	for(int i = 0; i < v.size(); i++){
		cout << v[i] << " ";
	}
}

int main(){
	int inputNumber;
	while(cin >> inputNumber){
		if(inputNumber % 2 == 0){
			evenVector.push_back(inputNumber);
		}else{
			oddVector.push_back(inputNumber);
		}
		for(int i = 0; i < 9; i++){
			cin >> inputNumber;
			if(inputNumber % 2 == 0){
				evenVector.push_back(inputNumber);
			}else{
				oddVector.push_back(inputNumber);
			}
		}
		if(oddVector.size() != 0){
			sort(oddVector.begin(), oddVector.end(), CompareDesc);
			Print(oddVector);
			oddVector.clear();
		}
		if(evenVector.size() != 0){
			sort(evenVector.begin(), evenVector.end(), CompareAsc);
			Print(evenVector);
			evenVector.clear();
		}
		cout << endl;
	}
	return 0;
}

6、题目描述:N只小白鼠(1 <= N <= 100),每只鼠头上戴着一顶有颜色的帽子。现在称出每只白鼠的重量,要求按照白鼠重量从大到小的顺序输出它们头上帽子的颜色。帽子的颜色用“red”,“blue”等字符串来表示。不同的小白鼠可以戴相同颜色的帽子。白鼠的重量用整数表示。【北京大学】

  • 输入格式:多案例输入,每个案例的输入第一行为一个整数N,表示小白鼠的数目。下面有N行,每行是一只白鼠的信息。第一个为不大于100的正整数,表示白鼠的重量,;第二个为字符串,表示白鼠的帽子颜色,字符串长度不超过10个字符。注意:白鼠的重量各不相同。
  • 输出格式:每个案例按照白鼠的重量从大到小的顺序输出白鼠的帽子颜色。
  • 样例输入:
    • 3
    • 30 red
    • 50 blue
    • 40 green
  • 样例输出:
    • blue
    • green
    • red

示例代码:

#include <iostream>
#include <map>
#include <string>

using namespace std;

map<int, string> myMap;

int main(){
	int n, weight;
	string color;
	while(cin >> n){
		for(int i = 0; i < n; i++){
			cin >> weight >> color;
			myMap[weight] = color;
		}
		for(map<int, string>::reverse_iterator iter = myMap.rbegin(); iter != myMap.rend(); iter++){
			cout << iter->second << endl;
		}
		myMap.clear();
	}
	return 0;
}

7、题目描述:按要求,给国家进行排名。【浙江大学】

  • 输入格式:有多组数据。第一行给出国家数N,要求排名的国家数M,国家号从0到N-1。第二行开始的N行给定国家或地区的奥运金牌数,奖牌数,人口数(百万)。接下来一行给出M个国家号。
  • 输出格式:排序有4种方式: 金牌总数 奖牌总数 金牌人口比例 奖牌人口比例 。对每个国家给出最佳排名排名方式 和 最终排名。格式为: 排名:排名方式。如果有相同的最终排名,则输出排名方式最小的那种排名,对于排名方式,金牌总数 < 奖牌总数 < 金牌人口比例 < 奖牌人口比例 。如果有并列排名的情况,即如果出现金牌总数为 100,90,90,80.则排名为1,2,2,4。每组数据后加一个空行。
  • 样例输入:
    • 4 4
    • 4 8 1
    • 6 6 2
    • 4 8 2
    • 2 12 4
    • 0 1 2 3
    • 4 2
    • 8 10 1
    • 8 11 2
    • 8 12 3
    • 8 13 4
    • 0 3
  • 样例输出:
    • 1:3
    • 1:1
    • 2:1
    • 1:2
    •  
    • 1:1
    • 1:1

示例代码:

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

const int MIN_VALUE = 99999999;

struct Country{
	int gold;               //金牌总数
	int total;              //奖牌总数
	int people;             //人口数
	int countryNo;          //国家号
	double goldPerPerson;   //金牌人口比例
	double totalPerPerson;  //奖牌人口比例
	int type1;              //金牌总数排名
	int type2;              //奖牌总数排名
	int type3;              //金牌人口比例排名
	int type4;              //奖牌人口比例排名
	Country(int g, int t, int p, int c, double gp, double tp):
		gold(g), total(t), people(p), countryNo(c), goldPerPerson(gp), totalPerPerson(tp){};
};

vector<Country> cVector;
vector<Country> result;

bool CompareGoldNumber(const Country &c1, const Country &c2){
	return c1.gold > c2.gold;
}

bool CompareTotalMedal(const Country &c1, const Country &c2){
	return c1.total > c2.total;
}

bool CompareGoldPerPerson(const Country &c1, const Country &c2){
	return c1.goldPerPerson > c2.goldPerPerson;
}

bool CompareMetalPerPerson(const Country &c1, const Country &c2){
	return c1.totalPerPerson > c2.totalPerPerson;
}

bool ComparecountryNo(const Country &c1, const Country &c2){
	return c1.countryNo < c2.countryNo;
}

int main(){
	int N, M;
	while(cin >> N >> M){
		int gold, total, people;
		for(int i = 0; i < N; i++){
			cin >> gold >> total >> people;
			double totalPerOrder = total * 1.0 / people;
			double goldPerOrder = gold * 1.0 / people;
			Country country(gold, total, people, i, goldPerOrder, totalPerOrder);
			cVector.push_back(country);
		}
		int index;
		for(int i = 0; i < M; i++){
			cin >> index;
			for(int j = 0; j < cVector.size(); j++){
				if(cVector[j].countryNo == index){
					result.push_back(cVector[j]);
					break;
				}
			}
		}
		sort(result.begin(), result.end(), CompareGoldNumber);
		result[0].type1 = 1;
		for(int i = 1; i < result.size(); i++){
			if(result[i].gold == result[i - 1].gold){
				result[i].type1 = result[i - 1].type1;
			}else{
				int count = 1, tmp = i;
				while(tmp - 2 >= 0 && result[tmp - 2].gold == result[tmp - 1].gold){
					tmp--;
					count++;
				}
				result[i].type1 = result[i - 1].type1 + count;
			}
		}
		sort(result.begin(), result.end(), CompareTotalMedal);
		result[0].type2 = 1;
		for(int i = 1; i < result.size(); i++){
			if(result[i].total == result[i - 1].total){
				result[i].type2 = result[i - 1].type2;
			}else{
				int count = 1, tmp = i;
				while(tmp - 2 >= 0 && result[tmp - 2].total == result[tmp - 1].total){
					tmp--;
					count++;
				}
				result[i].type2 = result[i - 1].type2 + count;
			}
		}
		sort(result.begin(), result.end(), CompareGoldPerPerson);
		result[0].type3 = 1;
		for(int i = 1; i < result.size(); i++){
			if(result[i].goldPerPerson == result[i - 1].goldPerPerson){
				result[i].type3 = result[i - 1].type3;
			}else{
				int count = 1, tmp = i;
				while(tmp - 2 >= 0 && result[tmp - 2].goldPerPerson == result[tmp - 1].goldPerPerson){
					tmp--;
					count++;
				}
				result[i].type3 = result[i - 1].type3 + count;
			}
		}
		sort(result.begin(), result.end(), CompareMetalPerPerson);
		result[0].type4 = 1;
		for(int i = 1; i < result.size(); i++){
			if(result[i].totalPerPerson == result[i - 1].totalPerPerson){
				result[i].type4 = result[i - 1].type4;
			}else{
				int count = 1, tmp = i;
				while(tmp - 2 >= 0 && result[tmp - 2].totalPerPerson == result[tmp - 1].totalPerPerson){
					tmp--;
					count++;
				}
				result[i].type4 = result[i - 1].type4 + count;
			}
		}
		sort(result.begin(), result.end(), ComparecountryNo);
		for(int i = 0; i < result.size(); i++){
			int min = MIN_VALUE, resultType;
			if(result[i].type1 < min){
				resultType = 1;
				min = result[i].type1;
			}
			if(result[i].type2 < min){
				resultType = 2;
				min = result[i].type2;
			}
			if(result[i].type3 < min){
				resultType = 3;
				min = result[i].type3;
			}
			if(result[i].type4 < min){
				resultType = 4;
				min = result[i].type4;
			}
			cout << min << ":" << resultType << endl;
		}
		cout << endl;
		cVector.clear();
		result.clear();
	}
	return 0;
}

8、题目描述:输入一个数n,然后输入n个数值各不相同,再输入一个值x,输出这个值在这个数组中的下标(从0开始,若不在数组中则输出-1)。【浙江大学】

  • 输入格式:测试数据有多组,输入n(1<=n<=200),接着输入n个数,然后输入x。
  • 输出格式:对于每组输入,请输出结果。
  • 样例输入:
    • 2
    • 1 3
    • 0
  • 样例输出:
    • -1

示例代码:

#include <iostream>
#include <vector>

using namespace std;

vector<int> myVector;

int main(){
	int n;
	while(cin >> n){
		int number, x;
		for(int i = 0; i < n; i++){
			cin >> number;
			myVector.push_back(number);
		}
		cin >> x;
		bool flag = true;
		for(int i = 0; i < myVector.size(); i++){
			if(myVector[i] == x){
				flag = false;
				cout << i << endl;
				break;
			}
		}
		if(flag){
			cout << "-1" << endl;
		}
		myVector.clear();
	}
	return 0;
}

9、题目描述:输入数组长度 n 输入数组      a[1...n] 输入查找个数m 输入查找数字b[1...m]   输出 YES or NO  查找有则YES 否则NO 。【北京邮电大学】

  • 输入格式:输入有多组数据。每组输入n,然后输入n个整数,再输入m,然后再输入m个整数(1<=m,n<=100)。
  • 输出格式:如果在n个数组中输出YES否则输出NO。
  • 样例输入:
    • 5
    • 1 5 2 4 3
    • 3
    • 2 5 6
  • 样例输出:
    • YES
    • YES
    • NO

示例代码:

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

vector<int> myVector;

int main(){
	int m, n;
	while(cin >> n){
		int number;
		for(int i = 0; i < n; i++){
			cin >> number;
			myVector.push_back(number);
		}
		sort(myVector.begin(), myVector.end());
		cin >> m;
		for(int i = 0; i < m; i++){
			cin >> number;
			string result = "NO";
			for(int j = 0; j < myVector.size(); j++){
				if(myVector[j] == number){
					result = "YES";
					break;
				}else if(myVector[j] > number){
					break;
				}
			}
			for(int i = 0; i < result.size(); i++){
				cout << result[i];
			}
			cout << endl;
		}
		myVector.clear();
	}
	return 0;
}

10、题目描述:第一行输入一个数n,1 <= n <= 1000,下面输入n行数据,每一行有两个数,分别是x y。输出一组x y,该组数据是所有数据中x最小,且在x相等的情况下y最小的。 【北京邮电大学】

  • 输入格式:输入有多组数据。每组输入n,然后输入n个整数对。
  • 输出格式:输出最小的整数对。
  • 样例输入:
    • 5  
    • 3 3  
    • 2 2  
    • 5 5  
    • 2 1  
    • 3 6
  • 样例输出:
    • 2 1

示例代码:

#include <iostream>

using namespace std;

const int MAX_N = -(1 << 31) - 1;

int main(){
	int n;
	int x, y;
	while(cin >> n){
		int min_x = MAX_N, min_y = MAX_N;
		for(int i = 0; i < n; i++){
			cin >> x >> y;
			if(x < min_x){
				min_x = x;
				min_y = y;
			}else if(x == min_x && y < min_y){
				min_y = y;
			}
		}
		cout << min_x << " " << min_y << endl;
	}
	return 0;
}

11、题目描述:在一个整数数组上,对于下标为i的整数,如果它大于所有它相邻的整数, 或者小于所有它相邻的整数,则称为该整数为一个极值点,极值点的下标就是i。【北京大学】

  • 输入格式:第一行是此数组的元素个数k(4<k<80),第二行是k个整数,每两个整数之间用空格分隔。
  • 输出格式:每个案例输出为n行:每行对应于相应数组的所有极值点下标值,下标值之间用空格分隔。
  • 样例输入:
    • 10
    • 10 12 12 11 11 12 23 24 12 12
    • 15
    • 12 12 122 112 222 211 222 221 76 36 31 234 256 76 76 
    • 15
    • 12 14 122 112 222 222 222 221 76 36 31 234 256 76 73
  • 样例输出:
    • 0 7
    • 2 3 4 5 6 10 12
    • 0 2 3 10 12 14

示例代码:

#include <iostream>
#include <vector>

using namespace std;

vector<int> myVector;
vector<int> result;

int main(){
	int n, inputNumber;
	while(cin >> n){
		for(int i = 0; i < n; i++){
			cin >> inputNumber;
			myVector.push_back(inputNumber);
		}
		for(int i = 0; i < myVector.size(); i++){
			if(i == 0){
				if(myVector[i] != myVector[i + 1]){
					result.push_back(i);
				}
			}else{
				if(i != myVector.size() - 1){
					if((myVector[i] > myVector[i - 1] && myVector[i] > myVector[i + 1]) ||
						(myVector[i] < myVector[i - 1] && myVector[i] < myVector[i + 1])){
						result.push_back(i);
					}
				}else{
					if(myVector[i] != myVector[i - 1]){
						result.push_back(i);
					}
				}
			}
		}
		for(int i = 0; i < result.size(); i++){
			cout << result[i] << " ";
		}
		cout << endl;
		myVector.clear();
		result.clear();
	}
	return 0;
}

12、题目描述:对给定的一个字符串,找出有重复的字符,并给出其位置,如:abcaaAB12ab12 输出:a,1;a,4;a,5;a,10,b,2;b,11,1,8;1,12, 2,9;2,13。【华中科技大学】

  • 输入格式:输入包括一个由字母和数字组成的字符串,其长度不超过100。
  • 输出格式:可能有多组测试数据,对于每组数据,按照样例输出的格式将字符出现的位置标出。1、下标从0开始。2、相同的字母在一行表示出其出现过的位置。
  • 样例输入:
    • abcaaAB12ab12
  • 样例输出:
    • a:0,a:3,a:4,a:9
    • b:1,b:10
    • 1:7,1:11
    • 2:8,2:12

示例代码:

#include <map>
#include <iostream>
#include <vector>
#include <string>

using namespace std;
map<char, vector<int> > myMap;
vector<char> orderVector;

int main(){
	string str;
	while(cin >> str){
		for(int i = 0; i < str.size(); i++){
			if(myMap.find(str[i]) == myMap.end()){
				orderVector.push_back(str[i]);
				vector<int> v;
				v.push_back(i);
				myMap[str[i]] = v;
			}else{
				vector<int> v = myMap[str[i]];
				v.push_back(i);
				myMap[str[i]] = v;
			}
		}
		for(int j = 0; j < orderVector.size(); j++){
			vector<int> v;
			for(map<char, vector<int> >::iterator iter = myMap.begin(); iter != myMap.end(); iter++){
				if(iter->first == orderVector[j]){
					v = iter->second;
					break;
				}
			}
			if(v.size() > 1){
				int i = 0;
				for(i = 0; i < v.size() - 1; i++){
					cout << orderVector[j] << ":" << v[i] << ",";
				}
				cout << orderVector[j] << ":" << v[i] << endl;
			}
		}
		myMap.clear();
		orderVector.clear();
	}
	return 0;
}

参考文献:

[1]杨泽邦、赵霖. 计算机考研——机试指南(第2版). [M]北京:电子工业出版社,2019.11;

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值