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
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
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, “ ,.-”);
把字符串按照后的符号分开,但仅能取出一个被分割的
#include
#include
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
}
}
#include
using namespace std;
int main()
{
char a[10] = {"abcd"};
for (int i = 0; a[i]; i++)
{
printf("%c ", a[i]);
}
return 0;
}
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<
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),冒泡排序
二分查找中中点的位置要写为 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++
#include
vector pile[maxn];
vector像是一个二维数组,一维大小固定,二维大小不固定
#include
#include
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;
}
#include
#include
using namespace std;
int main()
{
vector<vector<int>> v(3);
//v有3个元素,每个元素都是vector 容器
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
#include
#include
#include
#include
using namespace std;
struct BigInteger
{
static const int BASE = 100000000;
static const int WIDTH = 8;
vector 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;
}
双向队列,在两端增删元素具有较佳性能
所有适用于 vector的操作都适用于 deque
双向链表,在内存中不连续存放,不支持随机存取
#include
#include
#include
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;
}
队列,插入在尾部进行
删除,检索等只能在头部进行
#include
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
#include
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
}
}
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;
}
};
#include
#include
#include
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;
}
方法一:
binary_search(数组名+n1,数组名+n2,值);
返回布尔值
!!!a必须在b前面,b必须在a前面都不成立,不是==
方法二:
binary_search(数组名+n1,数组名+n2,值,排序规则结构名);
任意类型的规则,返回布尔值
!!!a必须在b前面,b必须在a前面都不成立,不是==
#include
#include
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;
}
方法一:
T * lower_bound(数组名+n1,数组名+n2,值)
返回一个指针T *p;
*p是查找区间下标最小的,大于“值”的元素,如果找不到则返回指向n2的元素
方法二:
T * lower_bound(数组名+n1,数组名+n2,值,排序规则结构名());
返回一个指针T *p;
#include
#include
#include
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;
}
需要在大量增加,删除数据的同时,还要进行大量数据的查找
希望增加数据,删除数据,产找数据都能在log(n)复杂度完成
排序+二分查找显然不可以,因加入新数据就要重新排序
就可以使用“平衡二叉树”数据结构存放数据,体现在STL中,就是以下四种“排序容器”
multiset set multimap map
multiset
定义了一个multiset变量st,st里面可以存放T类型的数据,并且自动排序
排序规则:表达式“a,则a排在b前面
可用st.insert添加元素,st.find查找元素,st.erase删除元素,复杂度都是log(n)
迭代器
multiset
i是迭代器,相当于指针,可用于指向multiset中的元素,访问multiset中的元素要通过迭代器
与指针不同:
multiset上迭代器可++,–,用!=和==比较,不可比大小,不可加减整数,不可相减
st.begin()返回值类型是multiset
是指向st中的头一个元素的迭代器
st.end()返回值类型是multiset
是指向st中的最后一个元素后面的迭代器
对迭代器++,其就指向容器中下一个元素,–则令其指向上一个元素
st.size()
#include
#include
#include
using namespace std;
int main()
{
multiset 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::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;
}
#include
#include
#include
using namespace std;
struct Rule1
{
bool operator()(const int& a, const int& b)
{//返回值为true则说明a必须排在b前面
return (a % 10) < (b % 10);
}
};
int main()
{
multiset>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>::iterator i;
for (i = st.begin(); i != st.end(); ++i)
{
cout << *i << ",";
}
cout << endl;
multisetst2;
//排序规则为个位数小的在前面
for (int i = 0; i < 10; ++i)
{
st2.insert(a[i]);
}
multiset::iterator p;
for (p = st2.begin(); p != st2.end(); ++p)
{
cout << *p << ",";
}
cout << endl;
p = st2.find(133);
cout << *p << endl;
return 0;
}
#include
#include
#include
#include
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()
{
multisetst;
for (int i = 0; i < 5; ++i)
{//插入的是students[i]
st.insert(students[i]);
}
multiset::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和multiset区别在于容器内不能有重复的元素
set插入元素可能不成功
#include
#include
#include
using namespace std;
int main()
{
setst;
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::iterator i;
for (i = st.begin(); i != st.end(); ++i)
{//只有8个元素
cout << *i << ",";
}
cout << endl;
struct
{
set::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容器里的元素,都是pair形式的 typedef multimap typedef int * PINT; 和multimap区别在于:
multimap
则mp里元素都是如下类型:
struct
{
T1 first
T2 second;
}
multimap中的元素按照dirst排序,并可以按照first进行查找
缺省的排序规则是 “a.first
此后MAP_STD 等价于multimap
此后PINT等价于 int*. 即PINT p;等价于int *p;#include
map
不能有关键字重复的元素
可以使用[],下标为关键字,返回值为first和关键字相同的元素的second
插入元素可能失败#include
map单词词频统计
#include