程序设计与算法郭炜老师的课堂笔记1

基础

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) 操作次数和问题无关
    • 对数复杂度
    • 线性复杂度
    • 多项式复杂度
    • 指数复杂度
    • 阶乘复杂度
  1. 无序数列中查找一个数:0(n)
  2. 平面上有n个点,找出任意两点间距离 0(n^2)
  3. 插入排序、选择排序、冒泡排序 0(n^2)
  4. 快速排序 0(n*log(n)) 快排的最坏复杂度就是0(n^2)是已经排好序的
  5. 二分查找 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(n
log(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的内容放入v
    cout << "1) " << v.end() - v.begin() << endl;
//两个随机迭代器可以相减,输出	1) 5
    cout << "2) ";
    PrintVector(v.begin(), v.end());
//2)	1 2	3 4	5
    v.insert(v.begin() + 2, 13); //在begin()+2位置插入	13
    cout << "3) ";
    PrintVector(v.begin(), v.end());
//3)	1 2	13 3	4	5
    v.erase(v.begin() + 2); //删除位于	begin() +	2的元素
    cout << "4) ";
    PrintVector(v.begin(), v.end());
//4)	1 2	3 4	5
    vector<int> v2(4, 100);    //v2 有4个元素,都是100
    v2.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	100
    v.erase(v.begin() + 1, v.begin() + 3);
//删除	v 上的一个区间,即	2,3
    cout << "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并清空lst2
    cout << "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 7
    
    int 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中的平衡二叉树数据结构

  1. 需要在大量增加,删除数据的同时,还要进行大量数据的查找

  2. 希望增加数据,删除数据,产找数据都能在log(n)复杂度完成

  3. 排序+二分查找显然不可以,因加入新数据就要重新排序

    就可以使用“平衡二叉树”数据结构存放数据,体现在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);//插入22
    	i = 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指向的元素,即12
    	for (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.info
		else 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;//输出98

	mp["Jack"] = 60;//修改名为“Jack”的元素的second
	for (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改为78
	MP::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;
}

猜你喜欢

转载自blog.csdn.net/zhj12399/article/details/112023782