误
string in, post;
struct node {
char a;
node* lchild, * rchild;
node(char x='\0') :a(x), lchild(nullptr), rchild(nullptr) {}
};
void so(node* r, int il, int ir, int pl, int pr) {
if (il > ir)return;
int root;
for (root = il; root <= ir; root++) {
if (in[root] == post[pr])break;
}//找到根节点在中序序列中的位置
r->a = in[root];
int lsize = root - il;//只含一个端点,不包含根节点root
so(r->lchild,il, root - 1, pl, pl + lsize - 1);//左子树
so(r->rchild,root + 1, ir, pl + lsize, pr - 1);//右子树
}
void pre(node* root) {
if (!root)return;
cout << root->a;
pre(root->lchild);
pre(root->rchild);
}
cin >> in >> post;
node* root = new node;
so(root, 0, in.length() - 1, 0, in.length() - 1);
pre(root);
一点基本常识,给你一个后序遍历,那么最后一个就是根(如ABCD,则根为D)
substr返回的是截取后的子串,第一个参数为开始截取的下标,第二个参数为截取的元素个数
find返回下标,
#include
#include
#include
#include
#include
#include
void so(string in, string pre) {
if (in.size() < 1)return;
char ch = pre[0];
int index = in.find(ch);//index代表根节点在中序序列中的下标位置,恰好代表左子树大小,因为左子树的最后一个元素下标为index-1,中有元素数量为index-1+1
so(in.substr(0, index), pre.substr(1, index));//左子树
so(in.substr(index + 1, in.size() - 1 - index), pre.substr(index + 1, in.size() - 1 - index));//右子树
cout << ch;
}//先序为根左右,中序为左根右
string in, pre;
cin >> in >> pre;
so(in, pre);
s.find(c);
//在字符串s中查找第一个字符c的位置,返回下标,如果没有返回string::npos
s.erase(it);
//在字符串中删除指针it所指向的字符
s.begin();
//返回s的首字符的指针(迭代器)
void b(string in, string a) {
if (in.size() > 0) {
char ch = a[a.size() - 1];
cout << ch;//中序为左根右,后序为左右根
int k = in.find(ch);//在中序里找根节点的下标,也代表左子树的大小
b(in.substr(0, k), a.substr(0, k));//左子树
b(in.substr(k + 1), a.substr(1, in.size() - 1 - k));//0是左子树的第一个元素,那么加上左子树大小,指向的是左子树后的第一个元素,即根节点,而不是左子树的最后一个元素,所以要加个1才是右子树的第一个元素
}
}
void so(string in, string pre) {
if (in.size() > 0) {
char ch = pre[0];
int index = in.find(ch);
so(in.substr(0, index), pre(1, index));//截取第二个参数个元素,从节点开始,所以是不包含右端点的
so(in.substr(index + 1, in.size() - 1 - index), pre.substr(1 + index, in.size() - 1 - index));
cout << ch;
}
}
必要条件为左右子树里都得有元素或者都没有,如果孩子里只有一个元素,因为前序后序的左右孩子都在根节点的一侧,所以就无法区分出这个孩子到底是左孩子还是右孩子,就会产生两种情况,有多少个只有一个孩子的情况,就会有1< 如果每个节点都有左右孩子或者没有,就不会有其它的情况,情况就是唯一的 重构二叉树干的就几件事,第一件是确定本层的节点,本层的根节点;然后划分出左右子树区间,递归解决 这个距离,就是说先向上找最近公共祖先,找的路径乘2,然后找到公共祖先再下来,就不用乘2 #include 快速排序 冒泡排序就是在一个序列当中,从起点开始,不断地往后冒泡交换,每次迭代确定一个最大值,随着冒泡次数的增多,然后最大值确定的也越来越多,需要相邻交换的次数越来越少 即外层循环n次,内层循环n-i次,整体是个n^2的复杂度 选择排序是从0开始保证序列的有序性,每次扩张序列的后一个数,然后和序列的最后一个数作比较,如果比序列的最后一个数大,那么就直接放着;不然,就往前移动,直到前一个数比它小,后一个数比它大,这个数就在有序序列中找到了自己的位置。 要么直接用queue,要么用数组模拟,用数组的话,一个指针表示队头指针,一个指针表示队尾,添加元素时,队尾增加,所以队尾指针增加;出队时,队头出,队头指针++ 就是队列里记录已经加入的每支股票的价格,然后先比较队头,直到队列为空或者不大于今天的价格就停止,操作完成后再入队今天的 遇到左括号入栈,遇到右括号出栈, 还有就是要注意括号的次序问题,就是把括号 看重复执行次数,为1+2+4+……+n,那么最后就是等比数列求和,N可以被视为2的指数次,用等比求和公式算,算完是On的复杂度 链表结点定义为(data,next},在P指向的结点之后插入结点S的代码是 S->next=P->next; P->next=S; 即遍历一次数组,但不需要做任何操作int nfind(char* inorder, int size, char v) {
for (int i = 0; i < size; i++) {
if (inorder[i] == v)return i;
}
}
node* build(char* preorder, char* inorder, int size) {//用char*的话,就是数组,只传数组名,即首个元素的下标接口
if (!size)return nullptr;
char rd = preorder[0];
int leftsize = nfind(inorder, size, rd);
node* root = new node(rd);
root->lchild = build(preorder + 1, inorder, leftsize);
root->rchild = build(preorder + 1 + leftsize, inorder + 1 + leftsize, size - 1 - leftsize);
return root;
}
node* buildpre(char* inorder, char* postorder, int size) {
if (!size)return nullptr;
char rd = postorder[size - 1];
int leftsize = nfind(inorder, size, rd);
node* root = new node(rd);
root->lchild = buildpre(inorder, postorder, leftsize);//加上的数代表差距,从头位置加上左子树的大小,那么最后指向的恰好是左子树后的第一个数,而不是左子树的最后一个数,因为起点不是0,而是1,是左子树里的第一个数
root->rchild = buildpre(inorder + 1 + leftsize, postorder + leftsize, size - 1 - leftsize);
return root;
}
node* buildin(char* preorder, char* postorder, int size) {
if (!size)return nullptr;
char rd = preorder[0];
node* root = new node(rd);//其它不用特判,因为可以构建出度为1的节点
if (size == 1)return root;//由于为满二叉树,此时每个序列要么为叶子节点,要么为出度为2的节点,这里检测前一种情况,即此时序列被拆的都只剩一个元素,不然序列里根本就不存后面的元素
int leftsize = nfind(postorder, size, preorder[1]);//由于根节点的位置在前序后序里的位置都是确定的,所以去找左子树的根节点
root->lchild = buildin(preorder + 1, postorder, leftsize);
root->rchild = buildin(preorder + 1 + leftsize, postorder, size - 1 - leftsize);//这里前一个参数要加1才是右子树的起点,因为要越过根节点和左子树,起点为左子树第一个元素,只加左子树大小时,指向根节点位置,再加1才是右子树的第一个元素位置
return root;//这里第一个为根节点,不是左子树的第一个元素,所以加完后指向的是左子树的最后一个元素,再加1就是右子树的第一个元素
}
TreeNode* buildTree(vector
层序重构树
void level(node*& t) {
queue
P3884 [JLOI2009] 二叉树问题
排序
插入排序
for (int i = 2; i <= n; i++) {
int temp = arr[i], j;
for ( j = i - 1; arr[j] > temp && j >= 1; j--) {
arr[j + 1] = arr[j];//向后移动这张牌
}
arr[j + 1] = temp;
}
for (int i = 2; i <= n; i++) {
int temp = arr[i], j;
for (j = i - 1; arr[j] > temp && j >= 1; j--) {//j代表的是此时比对的位置,从插入的牌的后面第一个开始
arr[j + 1] = arr[j];//向后移动这张牌
}//由于终止时要么不满足j<1,要么不满足arr[j]>temp,即arr[j]
归并排序
队列
7-1 模拟队列 分数 15
int p = 1, l = 0;
void push(int num) {
q[++l] = num;
}
void pop() {
p++;
}
bool empty() {
if (l >= p) {
return false;
}
else {
return true;
}
}
int query() {
return q[p];
}
7-3 大師と仙人との奇遇 分数 20
priority_queue
priority_queue
线性表、链表
7-2 后缀表达式求值
string s1;
stack
string s;
stack
7-1 字符串匹配问题(strs)
char a[] = { '{','[','(','<','}',']',')','>' };
int b[300], n;
cin >> n;
while (n--) {
string s;
cin >> s;
stack
检验栈序列
cin >> q;
while (q--) {
cin >> n;
stack
6-2 寻找链表元素的前驱结点
ptr pre(ptr h,int x){
ptr res=new node();
if(h==nullptr||h->data==x){return NULL;}
else{
res->next=h;
while(h!=NULL){
if(h->data==x){return res;}
res=h;
h=h->next;
}
}
return NULL;
/*if(h==NULL){return nullptr;}else{
return res;
}*/
}
线性表删除
List Delete( List &L, ElementType minD, ElementType maxD ){
int left=0;
int length=L.last;
for(int i=0;i<=length;i++){
if(L.Data[i]
栈
7-3 胡同
cin >> t;
while (t--) {
cin >> n;
for (int i = 1; i <= n; i++)cin >> a[i];
for (int i = 1; i <= n; i++)cin >> b[i];
stack
括弧匹配,弱化版
string s;
stack
选择题复习