程序设计与算法郭炜老师的课堂笔记1
程序设计与算法郭炜老师的课堂笔记1
- 基础
- 与或非
- 位运算
- 字符串操作库函数
- strtok尝试
- 字符串0新认识
- void 指针无定义
- 快排
- 变量
- 排序
- Vector
- vector示例
- 用**vector**实现二维数组
- 大整数类
- Deque
- List
- Queue
- STL算法
- 用sort进行排序
- 自定义排序规则
- 用sort进行排序二
- 用sort进行排序三:对结构进行排序
- STL查找是在排好序的数组上进行二分查找
- binary_search进行二分查找
- lower_bound 二分查找下界
- upper_bound 二分查找下界
- STL中的平衡二叉树数据结构
- multiset
- 自定义规则的multiset
- 自定义结构的规则的multiset
- set
- multimap
- map
- map单词词频统计
基础
sizeof(变量) 求占用字节数
#define MAX 1000
cin.get()是一个int变量
int c;
while ((c = cin.get()) != EOF)
{//用cin读入所有字符,包括空格换行cout << (char)c;
}
或
char c;
while (scanf("%c", &c) != EOF)
{printf("%c", c);
}
freopen(“E:\test.txt”, “r”, stdin);以后输入从文件里取
字符处理函数:
这些库函数在ctype中声明:
与或非
&
21: 00010101
18: 00010010
21&18:00010000 相当于是取交集,相同则为一
|:
21: 00010101
18: 00010010
21|18:00010111 相当于取并集
^:
21: 00010101
18: 00010010
21^18:00000111 相同为0,不同为一
~:
21: 00010101
~21: 11101010
9<<4:
00001001
10010000 每左移一位相当于乘2
9>>4:
每右移一位相当于除2
不通过第三个变量能实现交换两个变量的值
int a=5,b=7;
a=a^b;
b=b^a;
a=a^b;
字符串中 char a[2]要增添0的话,需为a[2]= ‘0’,而不是=0
使用cin.getline(char buf[],int bufsize)可避免越界
读入bufsize-1个字符
gets(char buf[]) 完整的读入一行,可能会越界
#include <cstring>
strcat(char []a,char []b);//b接到a后面
strupr(char [])转换为大写
strlwr(char [])转换为小写
遍历字符串操作:
for (int i = 0; a[i]; i++)
{printf("%c ", a[i]);
}
空指针:int *p=NULL或0但操作系统不允许访问该地址
函数形参:
void Fun( int *p) 或Fun(int p[])
位运算
#include <iostream>
using namespace std;
int main()
{int a, n;cin >> a >> n;a=a >> n;cout << a << endl;return 0;
}
字符串操作库函数
char *strchr(const char *str, int c);
寻找字符c在字符串中第一次出现的位置,如果找到返回其指针,不存在则返回NULL
char*strstr(const char*str,const char *substr);
寻找字符substr在str中第一次出现的位置,如果找到则返回该位置指针,不包含则返回NULL
int stricmp(const char *s1,const char *s2);
大小写无关的字符串比较
int strncmp(const char *s1,const char *s2);
比较s1前n个字符组成的子串和s2前n个字符组成的子串大小
char *strncpy(char *dest,const char *src, int n);
拷贝src的前n个字符到dest,如果长度大于n,该函数不会自动填充 ‘\0’
strtok(str, “ ,.-”);
把字符串按照后的符号分开,但仅能取出一个被分割的
strtok尝试
#include <iostream>
#include <cstring>
using namespace std;
int main()
{char a[] = { "hello,ok.nia" };char* p = a;p = strtok(a, ",.");while (p != NULL){//p不为空则说明找到了子串cout << p << endl;p = strtok(NULL, ",.");//后续调用开头为NULL}
}
字符串0新认识
#include <iostream>
using namespace std;
int main()
{char a[10] = {"abcd"};for (int i = 0; a[i]; i++) {printf("%c ", a[i]);}return 0;
}
void 指针无定义
voidmemset(voiddest,int ch,int n);
将从dest开始的n个字节都设置成ch
全部设置为0 int a[100];memset(a,0,sizeof(a));
void *memcpy(void dest,voidsrc,int n);
将src开始的n个字节拷贝到地址dest。返回值是dest
函数指针:
void (*pf)(int,int);
pf=Fun;
快排
void qsort(void base,int nelem,unsigned int width,int (pfCompare(const void,const void)));
快排 base为起始地址,nelem为元素个数,width为每一个元素大小,pfCompare比较函数的地址,由程序员自己编写
自己写的函数应该为:
MyCompare(const void*elem1, const void*elem2)
{//函数内部调用需进行强制类型转化unsigned int*p1,*p2;p1=(unsigned int*)elem1;
}
结构:
struct 结构名
{类型名 成员变量名;类型名 成员变量名;
};
struct Student
{unsigned ID;char szName[20];
float fGPA;
};
Student s1,s2;
//也可以结构套结构:
struct Date
{int year;int month;int day;
};
struct StudentEx
{unsigned ID;char szName[20];float fGPA;Date birthday;
};
初始化为: StudentEx stu={1234, “tom”,3.7,{1900,2,1}};
成员变量可以是指向本结构类型的变量的指针
struct employee
{string name;employee *next;
}
变量
静态变量:程序运行期间,存放地址不发生改变
全局变量都是静态变量,局部变量前增加static也可以变为静态变量
若未进行初始化,则静态变量会被自动初始化为全0,局部非静态变量的值则为随机.
静态变量的初始化语句只进行一次,以后都不会进行void func() {static int n = 4;//此句只执行一次cout<<n<<endl;++n; } int main() {func();func();func(); } //结果为4 5 6
char *Strtok(char *p,char *sep) {static char * start;//本次查找的起点if(p){start = p;}for(;*start && strchr(sep, *strat); ++start);//此循环跳过了分隔符号if(*start ==0){return NULL;}char *q = start;for(;*start && !strchr(sep, *start); ++start);//此循环跳过了非分隔符号if(*start){*start = 0;++start;}return q; }
排序
选择排序,插入排序0(n^2),冒泡排序
- 时间复杂度:
0(n) 0(n^2) 只按最大的次方来算
复杂度有平均复杂度和最坏复杂度,两者可能相同也可不同- 常数复杂度 0(1) 操作次数和问题无关
- 对数复杂度
- 线性复杂度
- 多项式复杂度
- 指数复杂度
- 阶乘复杂度
- 无序数列中查找一个数:0(n)
- 平面上有n个点,找出任意两点间距离 0(n^2)
- 插入排序、选择排序、冒泡排序 0(n^2)
- 快速排序 0(n*log(n)) 快排的最坏复杂度就是0(n^2)是已经排好序的
- 二分查找 0(log(n))
二分查找中中点的位置要写为 mid=L+(R-L)/2
而不是 (L+R)/2
例题:输入n个整数,找出其中两个数,使得之和等于整数m.
解法1:一一对应着去查找,0(n^2)
解法2:先进行快排0(nlog(n))在进行二分查找0(log(n))
解法3:先进行快排0(nlog(n)),a[i]+a[j]如果大于m,j–,小于则i++
Vector
#include <vector>
vector<int> pile[maxn];
vector像是一个二维数组,一维大小固定,二维大小不固定
vector示例
#include <iostream>
#include <vector>using namespace std;template<class T>void PrintVector(T s, T e)
{for (; s != e; ++s)cout << *s << " ";cout << endl;
}int main()
{int a[5] = {1, 2, 3, 4, 5};vector<int> v(a, a + 5); //将数组a的内容放入vcout << "1) " << v.end() - v.begin() << endl;
//两个随机迭代器可以相减,输出 1) 5cout << "2) ";PrintVector(v.begin(), v.end());
//2) 1 2 3 4 5v.insert(v.begin() + 2, 13); //在begin()+2位置插入 13cout << "3) ";PrintVector(v.begin(), v.end());
//3) 1 2 13 3 4 5v.erase(v.begin() + 2); //删除位于 begin() + 2的元素cout << "4) ";PrintVector(v.begin(), v.end());
//4) 1 2 3 4 5vector<int> v2(4, 100); //v2 有4个元素,都是100v2.insert(v2.begin(), v.begin() + 1, v.begin() + 3);
//将v的一段插入v2开头cout << "5) v2: ";PrintVector(v2.begin(), v2.end());
//5) v2: 2 3 100 100 100 100v.erase(v.begin() + 1, v.begin() + 3);
//删除 v 上的一个区间,即 2,3cout << "6) ";PrintVector(v.begin(), v.end());
//6) 1 4 5 return 0;
}
用vector实现二维数组
#include <iostream>
#include <vector>using namespace std;int main()
{vector<vector<int>> v(3);
//v有3个元素,每个元素都是vector<int> 容器for (int i = 0; i < v.size(); ++i){for (int j = 0; j < 4; ++j){v[i].push_back(j);}}for (int i = 0; i < v.size(); ++i){for (int j = 0; j < v[i].size(); ++j){cout << v[i][j] << " ";}cout << endl;}return 0;
}
大整数类
无需关注每个整数多大,vector会自动申请内存0
#include <vector>
#include <string>
#include <iostream>
#include <cstdio>
#include <cstdlib>using namespace std;struct BigInteger
{static const int BASE = 100000000;static const int WIDTH = 8;vector<int> s;BigInteger(long long num = 0){//构造函数*this = num;}BigInteger operator=(long long num){//赋值运算s.clear();do{s.push_back(num % BASE);num /= BASE;} while (num > 0);return *this;}BigInteger operator=(const string &str){//赋值运算s.clear();int x, len = (str.length() - 1) / WIDTH + 1;for (int i = 0; i < len; i++){int end = str.length() - i * WIDTH;int start = max(0, end - WIDTH);sscanf(str.substr(start, end - start).c_str(), "%d", &x);s.push_back(x);}return *this;}BigInteger operator+(const BigInteger &b) const{BigInteger c;c.s.clear();for (int i = 0, g = 0;; i++){if (g == 0 && i >= s.size() && i > b.s.size()){break;}int x = g;if (i < s.size()){x += s[i];}if (b.s.size()){x += b.s[i];}c.s.push_back(x % BASE);g = x / BASE;}return c;}BigInteger operator+=(const BigInteger &b){*this = *this + b;return *this;}bool operator<(const BigInteger &b) const{if (s.size() != b.s.size()){return s.size() < b.s.size();}for (int i = s.size() - 1; i >= 0; i--){if (s[i] != b.s[i]){return s[i] < b.s[i];}}return false;}
};ostream &operator<<(ostream &out, const BigInteger &x)
{out << x.s.back();for (int i = x.s.size() - 2; i >= 0; i--){char buf[20];sprintf(buf, "%08d", x.s[i]);for (int j = 0; j < strlen(buf); j++){out << buf[j];}}return out;
}istream &operator>>(istream &in, BigInteger &x)
{string s;if (!(in >> s)){return in;}x = s;return in;
}
Deque
双向队列,在两端增删元素具有较佳性能
所有适用于 vector的操作都适用于 deque
List
双向链表,在内存中不连续存放,不支持随机存取
#include <list>
#include <iostream>
#include <algorithm>using namespace std;class A
{private:int n;
public:A(int n_){ n = n_; }friend bool operator<(const A &a1, const A &a2);friend bool operator==(const A &a1, const A &a2);friend ostream &operator<<(ostream &o, const A &a);
};bool operator<(const A &a1, const A &a2)
{return a1.n < a2.n;
}bool operator==(const A &a1, const A &a2)
{return a1.n == a2.n;
}ostream &operator<<(ostream &o, const A &a)
{o << a.n;return o;
}template<class T>
void PrintList(const list<T> &lst)
{//不推荐的写法,还是用两个迭代器作为参数更好int tmp = lst.size();if (tmp > 0){typename list<T>::const_iterator i;i = lst.begin();for (i = lst.begin(); i != lst.end(); i++){cout << *i << ",";}}
}int main()
{list<A> lst1, lst2;lst1.push_back(1);lst1.push_back(3);lst1.push_back(2);lst1.push_back(4);lst1.push_back(2);lst2.push_back(10);lst2.push_front(20);lst2.push_back(30);lst2.push_back(30);lst2.push_back(30);lst2.push_front(40);lst2.push_back(40);cout << "1) ";PrintList(lst1);cout << endl;// 1) 1,3,2,4,2,cout << "2) ";PrintList(lst2);// 2) 40,20,10,30,30,30,40, cout << endl;lst2.sort();cout << "3) ";PrintList(lst2);cout << endl;//3) 10,20,30,30,30,40,40, lst2.pop_front();cout << "4) ";PrintList(lst2);cout << endl;//4) 20,30,30,30,40,40,lst1.remove(2); //删除所有和A(2)相等的元素cout << "5) ";PrintList(lst1);cout << endl;//5) 1,3,4,lst2.unique(); //删除所有和前一个元素相等的元素cout << "6) ";PrintList(lst2);cout << endl;//6) 20,30,40,lst1.merge(lst2); //合并 lst2到lst1并清空lst2cout << "7) ";PrintList(lst1);cout << endl;//7) 1,3,4,20,30,40,cout << "8) ";PrintList(lst2);cout << endl;//8)lst1.reverse();cout << "9) ";PrintList(lst1);cout << endl;//9) 40,30,20,4,3,1,lst2.push_back(100);lst2.push_back(200);lst2.push_back(300);lst2.push_back(400);list<A>::iterator p1, p2, p3;p1 = find(lst1.begin(), lst1.end(), 3);p2 = find(lst2.begin(), lst2.end(), 200);p3 = find(lst2.begin(), lst2.end(), 400);lst1.splice(p1, lst2, p2, p3);//将[p2,p3)插入p1之前,并从lst2中删除[p2,p3)cout << "10) ";PrintList(lst1);cout << endl;//10) 40,30,20,4,200,300,3,1,cout << "11) ";PrintList(lst2);cout << endl;//11) 100,400,return 0;
}
Queue
队列,插入在尾部进行
删除,检索等只能在头部进行
STL算法
#include<algorithm>
用sort进行排序
sort(数组名+n1,数组名+n2);n1省略即为从第一开始
int a[5] = { 9,7,3,8,6 };
sort(a, a+2);从小到大
sort从大到小排序:
sort(数组名+n1,数组名+n2,greater());
T代表基本类型数组 T=int
#include <iostream>
#include <algorithm>using namespace std;void print(int a[], int size)
{for (int i = 0; i < size; i++){cout << a[i] << ",";}cout << endl;
}struct Rule1
{//按从大到小排序bool operator()(const int& a1, const int& a2)const{return a1 > a2;}
};struct Rule2
{//按个位数从小到大排序bool operator()(const int& a1, const int& a2)const{return a1 % 10 < a2 % 10;}
};int main()
{int a[] = { 12,45,3,98,21,7 };sort(a, a + sizeof(a) / sizeof(int));cout << "1)从小到大: "; print(a, sizeof(a) / sizeof(int));sort(a, a + sizeof(a) / sizeof(int), Rule1());cout << "2)从大到小: "; print(a, sizeof(a) / sizeof(int));sort(a, a + sizeof(a) / sizeof(int), Rule2());cout << "3)按个位数从小到大: "; print(a, sizeof(a) / sizeof(int));
}
自定义排序规则
sort(数组名+n1,数组名+n2,排序规则结构名());
struct 结构名
{bool operator()(const T &a1,const T &a2)const {//若a1应该在a2前面,则返回true//否则返回false}
}
用sort进行排序二
struct Rule1
{//按从大到小排序bool operator()(const int &a1,const int &a2)const{return a1>a2;}
};struct Rule2
{//按个位数从小到大排序bool operator()(const int &a1,const int &a2)const{return a1%10 < a2%10;}
};
用sort进行排序三:对结构进行排序
#include <iostream>
#include <algorithm>
#include <cstring>using namespace std;struct Student
{char name[20];int id;double gpa;
};Student students[] =
{{"Jack",112,3.4},{"Mary",102,3.8},{"Maryl",117,3.9},{"Ala",333,3.5},{"Zero",101,4.0}
};struct StudentRule1
{//按姓名从小到大排bool operator()(const Student& s1, const Student& s2)const{if (strcmp(s1.name, s2.name) < 0){return true;}return false;}
};struct StudentRule2
{//按id从小到大排bool operator()(const Student& s1, const Student& s2)const{return s1.id < s2.id;}
};struct StudentRule3
{//按gpa从小到大排bool operator()(const Student& s1, const Student& s2)const{return s1.gpa < s2.gpa;}
};void PrintStudents(Student s[], int size)
{for (int i = 0; i < size; ++i){cout << "(" << s[i].name << "'" << s[i].id << ',' << s[i].gpa << ")";}cout << endl;
}int main()
{int n = sizeof(students) / sizeof(Student);sort(students, students + n, StudentRule1());PrintStudents(students, n);sort(students, students + n, StudentRule2());PrintStudents(students, n);sort(students, students + n, StudentRule3());PrintStudents(students, n);return 0;
}
STL查找是在排好序的数组上进行二分查找
binary_search进行二分查找
方法一:
binary_search(数组名+n1,数组名+n2,值);
返回布尔值
!!!a必须在b前面,b必须在a前面都不成立,不是==方法二:
binary_search(数组名+n1,数组名+n2,值,排序规则结构名);
任意类型的规则,返回布尔值
!!!a必须在b前面,b必须在a前面都不成立,不是==#include <iostream> #include <algorithm>using namespace std;struct Rule {//按个位从小到大排bool operator()(const int& a1, const int& a2){return a1 % 10 < a2 % 10;} };void Print(int a[], int size) {for (int i = 0; i < size; i++){cout << a[i] << ',';}cout << endl; }int main() {int a[] = { 12,45,3,98,21,7 };sort(a, a + 6);Print(a, 6);cout << "查找12:" << binary_search(a, a + 6, 12) << endl;cout << "查找77:" << binary_search(a, a + 6, 77) << endl;sort(a, a + 6, Rule());Print(a, 6);cout << "查找7:" << binary_search(a, a + 6, 7) << endl;//按个位排序后的正常查找是没有意义的cout << "查找8:" << binary_search(a, a + 6, 8, Rule()) << endl;//按原有只排个位数字就有意义了return 0; }
lower_bound 二分查找下界
- 方法一:
T * lower_bound(数组名+n1,数组名+n2,值)
返回一个指针T *p;
*p是查找区间下标最小的,大于等于“值”的元素,如果找不到则返回指向n2的元素 - 方法二:
T * lower_bound(数组名+n1,数组名+n2,值,排序规则结构名());
返回一个指针T *p;
upper_bound 二分查找下界
方法一:
T * lower_bound(数组名+n1,数组名+n2,值)
返回一个指针T *p;
*p是查找区间下标最小的,大于“值”的元素,如果找不到则返回指向n2的元素方法二:
T * lower_bound(数组名+n1,数组名+n2,值,排序规则结构名());
返回一个指针T *p;#include <iostream> #include <cstring> #include <algorithm>using namespace std;struct Rule {//个位数排序bool operator()(const int& a1, const int& a2){return a1 % 10 < a2 % 10;} };void Print(int a[], int size) {for (int i = 0; i < size; ++i){cout << a[i] << ",";}cout << endl; }#define NUM 7int main() {int a[NUM] = { 12,5,3,5,98,21,7 };sort(a, a + NUM);Print(a, NUM);int* p = lower_bound(a, a + NUM, 5);cout << *p << "p-a" << p - a << endl;p = upper_bound(a, a + NUM, 5);cout << *p << endl;cout << *upper_bound(a, a + NUM, 13) << endl;sort(a, a + NUM, Rule());Print(a, NUM);cout << *lower_bound(a, a + NUM, 16, Rule()) << endl;cout << lower_bound(a, a + NUM, 25, Rule()) - a << endl;cout << upper_bound(a, a + NUM, 18, Rule()) - a << endl;if (upper_bound(a, a + NUM, 18, Rule()) == a + NUM){cout << "not found" << endl;}cout << *upper_bound(a, a + NUM, 5, Rule()) << endl;cout << *upper_bound(a, a + NUM, 4, Rule()) << endl;return 0; }
STL中的平衡二叉树数据结构
需要在大量增加,删除数据的同时,还要进行大量数据的查找
希望增加数据,删除数据,产找数据都能在log(n)复杂度完成
排序+二分查找显然不可以,因加入新数据就要重新排序
就可以使用“平衡二叉树”数据结构存放数据,体现在STL中,就是以下四种“排序容器”
multiset set multimap map
multiset
multiset <T> st;
定义了一个multiset变量st,st里面可以存放T类型的数据,并且自动排序
排序规则:表达式 “a<b”为true
,则a排在b前面
可用st.insert添加元素,st.find查找元素,st.erase删除元素,复杂度都是log(n)
迭代器
multiset<int>::iterator i;
i是迭代器,相当于指针,可用于指向multiset中的元素,访问multiset中的元素要通过迭代器
与指针不同:
multiset上迭代器可++,–,用!=和==比较,不可比大小,不可加减整数,不可相减st.begin()返回值类型是
multiset<int>::iterator,
是指向st中的头一个元素的迭代器st.end()返回值类型是
multiset<int>::iterator,
是指向st中的最后一个元素后面的迭代器对迭代器++,其就指向容器中下一个元素,–则令其指向上一个元素
st.size()
#include <iostream> #include <cstring> #include <set>using namespace std;int main() {multiset<int> st;int a[10] = { 1,14,12,13,7,13,21,19,8,8 };for (int i = 0; i < 10; i++){//插入的是a[i]的复制品st.insert(a[i]);}//迭代器,类似于指针,这样来遍历数据multiset<int>::iterator i;for (i = st.begin(); i != st.end(); ++i){cout << *i << ",";}cout << endl;i = st.find(22);//查找22,返回值是迭代器if (i == st.end()){//找不到则返回值为end()cout << "not found" << endl;}st.insert(22);//插入22i = st.find(22);if (i == st.end()){cout << "not found" << endl;}else{//找到则返回指向找到的元素的迭代器cout << "found:" << *i << endl;}i = st.lower_bound(13);//返回最靠后的迭代器it,使得[begin(),it)中的元素都在13前面,复杂度log(n)cout << *i << endl;i = st.upper_bound(13);//返回最靠前的迭代器it,使得[it,end())中的元素都在8前面,复杂度log(n)cout << *i << endl;st.erase(i);//删除迭代器i指向的元素,即12for (i = st.begin(); i != st.end(); ++i){cout << *i << ",";}return 0; }
自定义规则的multiset
#include <iostream>
#include <cstring>
#include <set>using namespace std;struct Rule1
{bool operator()(const int& a, const int& b){//返回值为true则说明a必须排在b前面return (a % 10) < (b % 10);}
};int main()
{multiset<int, greater<int>>st;//排序规则为从大到小int a[10] = { 1,14,12,13,7,13,21,19,8,8 };for (int i = 0; i < 10; ++i){st.insert(a[i]);}multiset<int, greater<int>>::iterator i;for (i = st.begin(); i != st.end(); ++i){cout << *i << ",";}cout << endl;multiset<int, Rule1>st2;//排序规则为个位数小的在前面for (int i = 0; i < 10; ++i){st2.insert(a[i]);}multiset<int, Rule1>::iterator p;for (p = st2.begin(); p != st2.end(); ++p){cout << *p << ",";}cout << endl;p = st2.find(133);cout << *p << endl;return 0;
}
自定义结构的规则的multiset
#include <iostream>
#include <cstring>
#include <set>
#include <cstring>using namespace std;struct Student
{char name[20];int id;int score;
};Student students[] =
{{"Jack",112,78},{"Mary",102,85},{"Ala",333,92},{"Zero",101,70},{"Cindy",102,78}
};struct Rule
{bool operator()(const Student& a, const Student& b)const{if (a.score != b.score){return a.score > b.score;}else{return strcmp(a.name, b.name) < 0;}}
};int main()
{multiset<Student, Rule>st;for (int i = 0; i < 5; ++i){//插入的是students[i]st.insert(students[i]);}multiset<Student, Rule>::iterator p;for (p = st.begin(); p != st.end(); ++p){cout << p->score << " " << p->name << " " << p->id << endl;}Student s = { "Mary",1000,85 };p = st.find(s);if (p != st.end()){cout << p->score << " " << p->name << " " << p->id << endl;}return 0;
}
set
set和multiset区别在于容器内不能有重复的元素
set插入元素可能不成功
#include <iostream>
#include <cstring>
#include <set>using namespace std;int main()
{set<int>st;int a[10] = { 1,2,3,8,7,7,5,6,8,12 };for (int i = 0; i < 10; i++){st.insert(a[i]);}cout << st.size() << endl;set<int>::iterator i;for (i = st.begin(); i != st.end(); ++i){//只有8个元素cout << *i << ",";}cout << endl;struct{set<int>::iterator first;bool second;} result = st.insert(2);if (! result.second){//条件成立说明插入不成功cout << *result.first << "already exists." << endl;}else{cout << *result.first << "inserted." << endl;}return 0;
}
multimap
multimap容器里的元素,都是pair形式的
multimap<T1,T2> mp;
则mp里元素都是如下类型:
struct
{
T1 first
T2 second;
}
multimap中的元素按照dirst排序,并可以按照first进行查找
缺省的排序规则是 “a.first<b.first”为true,则a排在b前面
typedef multimap<int, StudentInfo> MAP_STD;
此后MAP_STD 等价于multimap<int, StudentInfo>
typedef int * PINT;
此后PINT等价于 int*. 即PINT p;等价于int *p;
#include <iostream>
#include <map>
#include <cstring>using namespace std;struct StudentInfo
{int id;char name[20];
};struct Student
{int score;StudentInfo info;
};typedef multimap<int, StudentInfo> MAP_STD;int main()
{MAP_STD mp;Student st;char cmd[20];while (cin >> cmd){if (cmd[0] == 'A'){cin >> st.info.name >> st.info.id >> st.score;mp.insert(make_pair(st.score, st.info));}//make_pair生成一个pair<int,StudentInfo>变量//其first等于st.score,second等于st.infoelse if (cmd[0] == 'Q'){int score;cin >> score;MAP_STD::iterator p = mp.lower_bound(score);if (p != mp.begin()){--p;score = p->first;//比要查询分数低的最高分MAP_STD::iterator maxp = p;int maxId = p->second.id;for (; p != mp.begin() && p->first == score; --p){//遍历所有成绩和score相等的学生if (p->second.id > maxId){maxp = p;maxId = p->second.id;}}if (p->first == score){//如果上面循环是因为p==mp.begin()而终止,//则p指向的元素还要处理if (p->second.id > maxId){maxp = p;maxId = p->second.id;}}cout << maxp->second.name << " "<< maxp->second.id << " "<< maxp->first << endl;}//lower_bound的结果就是begin.说明没任分数比查询分数低else{cout << "Nobody" << endl;} }}return 0;
}
map
和multimap区别在于:
不能有关键字重复的元素
可以使用[],下标为关键字,返回值为first和关键字相同的元素的second
插入元素可能失败
#include <iostream>
#include <map>
#include <cstring>
using namespace std;struct Student
{string name;int score;
};Student students[5] =
{{"Jack",89},{"Tom",74},{"Cindy",87},{"Alysa",87},{"Micheal",98}
};typedef map<string, int> MP;int main()
{MP mp;for (int i = 0; i < 5; i++){mp.insert(make_pair(students[i].name, students[i].score));}cout << mp["Jack"] << endl;//输出98mp["Jack"] = 60;//修改名为“Jack”的元素的secondfor (MP::iterator i = mp.begin(); i != mp.end(); ++i){cout << "(" << i->first << "," << i->second << ")";}cout << endl;Student st;st.name = "Jack";st.score = 99;pair<MP::iterator, bool> p =mp.insert(make_pair(st.name, st.score));if (p.second){cout << "(" << p.first->first << "," << p.first->second << ")inserted" << endl;}else{//输出此信息cout << "insertion failed" << endl;}mp["Harry"] = 78;//插入一元素,其first为“Harry”,然后将其second改为78MP::iterator q = mp.find("Harry");cout << "(" << q->first << "," << q->second << ")" << endl;return 0;
}
map单词词频统计
#include <iostream>
#include <map>
#include <set>
#include <cstring>
using namespace std;struct Word
{int times;string wd;
};struct Rule
{bool operator()(const Word& w1, const Word& w2){if (w1.times != w2.times){return w1.times > w2.times;}else{return w1.wd < w2.wd;}}
};int main()
{string s;set<Word, Rule>st;map<string, int>mp;while (cin >> s){++mp[s];}for (map<string, int>::iterator i = mp.begin();i != mp.end(); ++i){Word tmp;tmp.wd = i->first;tmp.times = i->second;st.insert(tmp);}for (set<Word, Rule>::iterator i = st.begin();i != st.end(); ++i){cout << i->wd << " " << i->times << endl;}return 0;
}
程序设计与算法郭炜老师的课堂笔记1相关推荐
- 程序设计与算法郭炜老师的课堂笔记2
程序设计与算法郭炜老师的课堂笔记2 枚举 完美立方 生理周期 称硬币 熄灯问题 递归 求阶乘 汉诺塔 N皇后 逆波兰表达式 表达式求值 上台阶 放苹果 算24 二分算法 找一对数 分治 归并排序 快速 ...
- 程序设计与算法郭炜老师的课堂笔记3
程序设计与算法郭炜老师的课堂笔记3 从C到C++ 引用 引用作为函数参数 引用作为函数返回值 常引用 const关键字 定义常量 定义常量指针 定义常引用 动态内存分配 用new开内存 用delete ...
- xmuoj《C++与Python语法入门练习(By郭炜老师)》python参考代码
目录 前言 xmuoj对应链接 Pycharm安装 代码 001 输出第二个整数 002 字符菱形 003 打印ASCII码 004 打印字符 005 整型数据类型存储空间大小 006 浮点型数据类型 ...
- AI公开课:19.04.17杨松帆—好未来AI Lab负责人《为人工智能时代打造一个AI老师》课堂笔记以及个人感悟
AI公开课:19.04.17杨松帆-好未来AI Lab负责人<为人工智能时代打造一个AI老师>课堂笔记以及个人感悟 导读 杨松帆,现为好未来教育集团人工智能实验室负责人.曾任FaceThi ...
- 郭炜老师 程序设计与算法(二) 枚举
枚举:(一)完美立方 题目: 题解: 设计abcd四个属性的遍历范围和遍历顺序,使用for循环进行遍历 总结: 枚举需要注意枚举的范围,一般只需要给出一个大致范围,不需要十分精确的计算 枚举还需要注意 ...
- 例题代码|程序设计与算法(二) 算法基础 北大 郭炜 中国大学MOOC 笔记
网站链接
- 郭炜老师魔兽三备战思路及代码
这个题目,我花了差不多4天才全部做出来的,一开始也没很好的设计,就是看见有什么功能,就写一个函数的声明,然后写另一个类的时候,发现我要用到前面写的类的函数时,才去定义相应的函数,所以可能会很混乱.我写 ...
- 北大郭炜《程序设计与算法(三)》Mooc笔记:运算符重载和继承
文章目录 运算符重载 运算符重载的基本概念 赋值运算符的重载 为什么引入赋值运算符重载? 浅拷贝和深拷贝 对operator=返回值的讨论 复制构造函数的相同困境 运算符重载为友元函数 实例:可变长数 ...
- Python1.语言基本要素上(郭炜老师python大学mooc)
首先是 程序中的所有字符都必须是英文字符,不能是中文的全角字符, 除非输出中文,才会在"字符串"中使用中文 目录 一.注释 二.变量 三.赋值语句 四.字符串初步 五.字符串和数的 ...
最新文章
- Nmap Windows 版本时区显示乱码
- Apollo进阶课程㉑丨Apollo规划技术详解——Basic Motion Planning and Overview
- OpenVINO Inference Engine之LoadNetwork
- Elasticsearch】 es Match Query
- 编译安装imagick出错:make: *** [imagick_class.lo] Error 1
- 华为-----任正非
- shiro 认证和授权原理
- windows PAE扩展和AWE编程
- MFC加入mysql后编译成功,在自己电脑上成功运行,当打包发送到其他电脑上报错, 缺少libcrypto-1_1-x64.dll以及缺少libssl-1_1-x64.dll问题解决方案,完美亲测
- Linux自学之MPD
- erp5,一套基于python和gpl协议,功能和界面完全模仿sap r3的大型开源制造业erp系统
- 德卡t10社保卡类型_德卡T10社保卡读卡器非接触式ic卡医保卡二代证医院挂号卡...
- snkrs抽签协议获取
- 2908. Annoying painting tool
- 我如何构建Pomodoro Clock应用程序,以及在此过程中学到的课程
- vue axios常用写法
- 【Qcom Camera】微距eeprom调试
- 解决Python打包exe控制台无法粘贴问题
- “伪智能”厂商能有什么坏心思,无非是想骗钱罢了
- python 英语分词是什么意思_英语里面现在分词是什么意思