记录TITOCHAN学习数据结构的历程
链表
单链表
例题 手敲链表
用C++语言和类实现单链表,含头结点
属性包括:data数据域、next指针域
操作包括:插入、删除、查找
注意:单链表不是数组,所以位置从1开始对应首结点,头结点不放数据
类定义参考
Input
- 第1行先输入n表示有n个数据,接着输入n个数据
- 第2行输入要插入的位置和新数据
- 第3行输入要插入的位置和新数据
- 第4行输入要删除的位置
- 第5行输入要删除的位置
- 第6行输入要查找的位置
- 第7行输入要查找的位置
Output
数据之间用空格隔开,
第1行输出创建后的单链表的数据
每成功执行一次操作(插入或删除),输出执行后的单链表数据
每成功执行一次查找,输出查找到的数据
如果执行操作失败(包括插入、删除、查找等失败),输出字符串error,不必输出单链表
code
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
class p
{
public:
int data;
p* next;
p()
{
next=NULL;
}
};
p* head = new p();
void print_(p* q)
{
while (q->next != NULL)
{
printf("%d ", q->next->data);
q = q->next;
}
printf("\n");
}
void cha(p* q)
{
int w,i=0,n;
cin>>w>>n;
w--;
while (q->next != NULL)
{
if(w==i)
{
p* s= new p();
s->data=n;
s-> next=q->next;
q->next=s;
break;
}
q = q->next;
i++;
}
if(q->next==NULL&&i==w)
{
p* s = new p();
s->data=n;
s->next = NULL;
q->next = s;
q= head;
print_(q);
}
else if(q->next==NULL)
{
cout<<"error\n";
}
else
{
q= head;
print_(q);
}
}
void del(p* q)
{
int w,i=0;
cin>>w;
w--;
while (q->next != NULL)
{
if(w==i)
{
p* s= new p();
s=q->next;
q->next=s->next;
break;
}
q = q->next;
i++;
}
if(q->next==NULL)
{
cout<<"error\n";
}
else
{
q= head;
print_(q);
}
}
void find(p* q)
{
int w,i=0;
cin>>w;
if(w==0) w--;
while (q->next != NULL)
{
if(w==i)
{
cout<<q->data;
break;
}
q = q->next;
i++;
}
if(q->next==NULL&&i==w)
{
cout<<q->data;
}
else if(q->next==NULL)
{
cout<<"error\n";
}
else
{
q= head;
}
}
int main()
{
p* q = new p();
head=q;
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++)
{
p* s= new p();
scanf("%d", &s->data);
q->next = s;
s->next = NULL;
q = s;
}
q= head;
print_(q);
int w,i=0;
cha(q);
q=head;
cha(q);
q=head;
del(q);
q=head;
del(q);
q=head;
find(q);
q=head;
find(q);
q=head;
}
例题 一元多项式
对于一元多项式
p(x)=p0+p1x+p2x2+ … +pnxn,
每个项都有系数和指数两部分,例如p2x2的系数为p2,指数为2。
编程实现两个多项式的相加。
例如
5+x+2x2+3x3,-5-x+6x2+4x4,
两者相加结果:
8x2+3x3+4x4
其中系数5和-5都是x的0次方的系数,相加后为0,所以不显示。x的1次方同理不显示。
请用链表实现。
Input
第1行:输入t表示有t组测试数据
第2行:输入n表示有第1组的第1个多项式包含n个项
第3行:输入第一项的系数和指数,以此类推输入n行
接着输入m表示第1组的第2个多项式包含m项
同理输入第2个多项式的m个项的系数和指数
参考上面输入第2组数据,以此类推输入t组
假设所有数据都是整数
Output
对于每1组数据,先用两行输出两个原来的多项式,再用一行输出运算结果,不必考虑结果全为0的情况
输出格式参考样本数据,格式要求包括:
1.如果指数或系数是负数,用小括号括起来。
2.如果系数为0,则该项不用输出。
3.如果指数不为0,则用符号 ^
表示,例如x的3次方,表示为 x^3
。
4.多项式的每个项之间用符号+连接,每个+两边加1个空格隔开。
Sample
Input
2
4
5 0
1 1
2 2
3 3
4
-5 0
-1 1
6 2
4 4
3
-3 0
-5 1
2 2
4
9 -1
2 0
3 1
-2 2
Output
5 + 1x^1 + 2x^2 + 3x^3
(-5) + (-1)x^1 + 6x^2 + 4x^4
8x^2 + 3x^3 + 4x^4
(-3) + (-5)x^1 + 2x^2
9x^(-1) + 2 + 3x^1 + (-2)x^2
9x^(-1) + (-1) + (-2)x^1
code
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
struct pt {
int z, x;
struct pt* next;
pt() {
next = nullptr;
}
};
int main()
{
int t, n;
cin >> t;
while (t--)
{
cin >> n;
int x, z, l = -50;
//int a[100][2];
pt* h1 = new pt();
pt* p = h1;
for (int i = 0;i < 99;i++)
{
p->x = 0;
p->z = l++;
pt* s = new pt();
p->next = s;
p = p->next;
}
int m = n;
while (n--)
{
cin >> x >> z;
p = h1;
for (int j = 0;j < 99;j++)
{
if (p->z == z)
{
p->x += x;
}
p = p->next;
}
}
n = m;
int f = 0;
p = h1;
for (int i = 0;i < 99;i++)
{
if (p->x != 0)
{
if (f == 0)
{
f = 1;
}
else cout << " + ";
if (p->x > 0)
cout << p->x;
else cout << "(" << p->x << ")";
if (p->z > 0)
cout << "x^" << p->z;
else if (p->z == 0);
else cout << "x^" << "(" << p->z << ")";
}
p = p->next;
}
cout << endl;
cin >> m;
n += m;
//int b[100][2];
pt* h2 = new pt();
pt* q = h2;
l = -50;
for (int i = 0;i < 99;i++)
{
q->x = 0;
q->z = l++;
pt* s = new pt();
q->next = s;
q = q->next;
}
while (m--)
{
cin >> x >> z;
q = h2;
for (int j = 0;j < 99;j++)
{
if (q->z == z)
{
q->x += x;
}
q = q->next;
}
}
f = 0;
q = h2;
for (int i = 0;i < 99;i++)
{
if (q->x != 0)
{
if (f == 0)
{
f = 1;
}
else cout << " + ";
if (q->x > 0)
cout << q->x;
else cout << "(" << q->x << ")";
if (q->z > 0)
cout << "x^" << q->z;
else if (q->z == 0);
else cout << "x^" << "(" << q->z << ")";
}
q = q->next;
}
cout << endl;
q = h2;
p = h1;
for (int i = 0;i < 99;i++)
{
p->x += q->x;
q = q->next;
p = p->next;
}
f = 0;
p = h1;
for (int i = 0;i < 99;i++)
{
if (p->x != 0)
{
if (f == 0)
{
f = 1;
}
else cout << " + ";
if (p->x > 0)
cout << p->x;
else cout << "(" << p->x << ")";
if (p->z > 0)
cout << "x^" << p->z;
else if (p->z == 0);
else cout << "x^" << "(" << p->z << ")";
}
p = p->next;
}
cout << endl;
}
}
栈和队列
Description迷宫走法
给出一个N*N的迷宫矩阵示意图,从起点[0,0]出发,寻找路径到达终点[N-1, N-1]
要求使用堆栈对象来实现,具体算法参考课本3.2.4节51页
Input
第一行输入t,表示有t个迷宫
第二行输入n,表示第一个迷宫有n行n列
第三行起,输入迷宫每一行的每个方格的状态,0表示可通过,1表示不可通过
输入n行
以此类推输入下一个迷宫
Output
逐个输出迷宫的路径
如果迷宫不存在路径,则输出no path并回车
如果迷宫存在路径,将路径中每个方格的x和y坐标输出,从起点到终点,每输出四个方格就换行,最终以单词END结尾,具体格式参考示范数据
输出的代码参考如下:
#include<iostream>
#include<queue>
#include<stack>
#include<cstring>
using namespace std;
struct xy {
int x, y;
};
void migong()
{
int t;
cin >> t;
while (t--)
{
stack<xy> w;
int n;
cin >> n;
int** mi = new int* [n];
for (int i = 0;i < n;i++)
{
mi[i] = new int[n];
for (int j = 0;j < n;j++)
{
cin >> mi[i][j];
}
}
if (mi[0][0] == 1)
{
cout << "no path\n";
}
else {
bool f = 0;
w.push({ 0,0 });
mi[0][0] = 1;
int i = 0, j = 0;
while (1)
{
if (j + 1 < n && mi[i][j + 1] == 0) //xiangyouzou
{
if (f == 0)
{
mi[i][j + 1] = 1;
w.push({ i,++j });
}
}
else if (i + 1 < n && mi[i + 1][j] == 0) //xiangxiazou
{
if (f == 0)
{
mi[i + 1][j] = 1;
w.push({ ++i,j });
}
}
else if (j - 1 >= 0 && mi[i][j - 1] == 0) //xiangzuozou
{
if (f == 0)
{
mi[i][j - 1] = 1;
w.push({ i,--j });
}
}
else if (i - 1 >= 0 && mi[i - 1][j] == 0) //xiangshangzou
{
if (f == 0)
{
mi[i - 1][j] = 1;
w.push({ --i,j });
}
}
else {
w.pop();
if (!w.empty())
{
i = w.top().x;
j = w.top().y;
}
}
if (w.empty() || (i == n - 1 && j == n - 1))
{
f = 1;
break;
}
}
if (w.empty()) {
cout << "no path" << endl;
}
else {
stack<xy> path1;
while (!w.empty()) {
path1.push(w.top());
w.pop();
}
i = 0;
while (!path1.empty()) {
if ((++i) % 4 == 0) {
cout << '[' << path1.top().x << ',' << path1.top().y << ']' << "--" << endl;
}
else {
cout << '[' << path1.top().x << ',' << path1.top().y << ']' << "--";
}
path1.pop();
}
cout << "END" << endl;
}
}
for (int i = 0; i < n; i++)
delete[]mi[i];
delete[]mi;
}
// for(int i=0;i<n;i++)
// {
//
// for(int j=0;j<n;j++)
// {
// cout<<mi[i][j]<<" ";
// }
// cout<<endl;
// }
}
int main()
{
migong();
return 0;
}
Description算数
计算一个表达式的运算结果
使用C++自带stack堆栈对象来实现
例如
Push (OPTR, '#');
表示把字符#
压入堆栈OPTR
中,转换成c++代码就是OPTR.push('#');
Pop(OPND, a);
表示弹出栈OPND
的栈顶元素,并把栈顶元素放入变量a
中。因此改成c++代码是两个操作:a = OPND.top(); OPND.pop();
a = GetTop(OPND);
表示获取栈OPND
的栈顶元素,转成c++代码就是: `a = OPND.top();
参考课本的伪代码,把伪代码改造成可运行的代码
Input
第一个输入t,表示有t个实例
第二行起,每行输入一个表达式,每个表达式末尾带#表示结束
输入t行
Output
每行输出一个表达式的计算结果,计算结果用浮点数(含4位小数)的格式表示
#include <iostream>
#include <string>
#include <stack>
#include <iomanip>
using namespace std;
int Status;
char Prior[7][7] = {
'>', '>', '<', '<', '<', '>', '>',
'>', '>', '<', '<', '<', '>', '>',
'>', '>', '>', '>', '<', '>', '>',
'>', '>', '>', '>', '<', '>', '>',
'<', '<', '<', '<', '<', '=', ' ',
'>', '>', '>', '>', ' ', '>', ' ',
'<', '<', '<', '<', '<', ' ', '=' };
char OPSET[7] = { '+', '-', '*', '/', '(', ')', '#' };
bool shifuhao(char c)
{
for (int i = 0; i < 7; i++)
{
if (c == OPSET[i])
{
return true;
}
}
return false;
}
int precede(char a, char b)
{
int i, j;
for (i = 0; i < 7; i++)
{
if (a == OPSET[i])
{
break;
}
}
for (j = 0; j < 7; j++)
{
if (b == OPSET[j])
{
break;
}
}
return Prior[i][j];
}
float Operate(float a, char theta, float b)
{
switch (theta)
{
case '+':
return a + b;
case '-':
return a - b;
case '*':
return a * b;
case '/':
return a / b;
default:
return 0;
}
}
float EvaluateExpression(const string& expr)
{
stack<char> OPTR;
stack<float> OPND;
OPTR.push('#');
string expression = expr + '#';
int i = 0;
while (!OPTR.empty())
{
char c = expression[i];
if (!shifuhao(c))
{
string number;
while ((c <= '9' && c >= '0') || c == '.' || (c == '-' && (i == 0 || expression[i - 1] == '(')))
{
number += c;
c = expression[++i];
}
OPND.push(stof(number));
}
else
{
switch (precede(OPTR.top(), c))
{
case '<':
OPTR.push(c);
i++;
break;
case '=':
OPTR.pop();
i++;
break;
case '>':
char theta = OPTR.top();
OPTR.pop();
float b = OPND.top();
OPND.pop();
float a = OPND.top();
OPND.pop();
OPND.push(Operate(a, theta, b));
break;
}
}
}
return OPND.top();
}
int main()
{
int t;
cin >> t;
cin.ignore();
for (int i = 0; i < t; i++)
{
string expr;
cin >> expr;
float result = EvaluateExpression(expr);
cout << fixed << setprecision(4) << result << endl;
}
return 0;
}
链表队列
#include <iostream>
#include <string>
#include <stack>
#include <iomanip>
using namespace std;
struct node {
int data;
struct node* next;
};
struct node* front = NULL;
struct node* rear = NULL;
void enqueue(int x)
{
struct node* temp = (struct node*)malloc(sizeof(struct node*));
temp -> data = x;
temp->next = NULL;
if (front == NULL && rear == NULL)
{
front = rear = temp;
return;
}
rear->next = temp;
rear = temp;
}
int dequeue()
{
struct node* temp = front;
if (front == NULL)
return 0;
if (front == rear)
{
front = rear = NULL;
}
else {
front = front->next;
}
return temp->data;
free(temp);
}
int main()
{
int t,a;
cin >> t;
for (int i = 0; i < t; i++)
{
cin >> a;
enqueue(a);
}
for (int i = 0; i < t; i++)
{
cout<<dequeue();
}
return 0;
}
进制转换
#include <iostream>
#include <string>
#include <stack>
#include <queue>
#include <iomanip>
using namespace std;
int main()
{
int t;
cin >> t;
while (t--)
{
double f;
int jin,fi;
cin >> f >> jin;
fi = f;
f -= fi;
stack<int> pq;
queue<int> ph;
//cout << fi << f;
while (fi != 0)
{
pq.push(fi % jin);
fi /= jin;
}
int zs=1;
int sun = 0;
while (f != (int)f)
{
if (sun++ == 3)
{
break;
}
f *= jin;
zs=f;
ph.push(zs);
f-=zs;
}
while (!pq.empty())
{
if (pq.top() > 9)
{
cout << (char)('A' - 10 + pq.top());
}
else cout << pq.top();
pq.pop();
}
cout << ".";
sun = 0;
while (!ph.empty())
{
if (ph.front() > 9)
{
cout << (char)('A' - 10 + ph.front());
}
else cout << ph.front();
ph.pop();
sun++;
}
for (;sun < 3;sun++)
{
cout << "0";
}
cout << endl;
}
return 0;
}
DS队列–组队列
此题本来一开始想要偷懒 用了以下代码
#include<iostream>
#include<queue>
using namespace std;
int main()
{
int t;
int data;
int cha[2000] = { 0 };
int flag = 1;
int n;
cin >> t;
queue<int> *q=new queue<int>[t];
queue<int> r;
for (int i = 0;i < t;i++)
{
cin >> n;
while (n--)
{
cin >> data;
cha[data] = i;
}
}
string c;
cin >> c;
int be = 0;
while (c != "STOP")
{
if (c == "ENQUEUE")
{
cin >> data;
for (int i = be;i < t+be;i++)
{
if (q[i].empty() || cha[q[i].front()] == cha[data])
{
q[i].push(data);
break;
}
}
}
else if (c == "DEQUEUE")
{
for (int i =be;i < t+be;i++)
{
if (!q[i].empty())
{
r.push(q[i].front());
//cout << q[i].front();
q[i].pop();
break;
}
}
}
cin >> c;
}
while (!r.empty())
{
if (flag == 1)
{
flag = 0;
cout << r.front();
}
else
cout << " " << r.front();
r.pop();
}
cout << endl;
return 0;
}
最后还是选择了重新写
脑壳疼
#include <iostream>
#include <queue>
using namespace std;
int main()
{
int n, e, p;
cin >> n;
queue<int>* q = new queue<int>[n];
vector<int>* cha = new vector<int>[n];
queue<int> res;
queue<int> pq;
bool* flag = new bool[n];
for (int i = 0; i < n; i++)
flag[i] = 0;
for (int i = 0; i < n; i++)
{
cin >> p;
while (p--)
{
cin >> e;
cha[i].push_back(e);
}
}
string c;
while (1)
{
cin >> c;
if (c == "STOP")
break;
if (c == "ENQUEUE")
{
cin >> e;
bool pan = 0;
for (int i = 0; i < n; i++)
{
for (auto& it : cha[i])
{
if (it == e)
{
if (!flag[i])
{
pq.push(i);
flag[i] = 1;
}
q[i].push(e);
pan = 1;
break;
}
}
if (pan)
break;
}
if (!pan)
{
q[n - 1].push(e);
cha[n - 1].push_back(e);
}
}
else
{
res.push(q[pq.front()].front());
q[pq.front()].pop();
if (q[pq.front()].empty())
{
flag[pq.front()] = 0;
pq.pop();
}
}
}
size_t num = res.size();
for (size_t i = 0; i < num - 1; i++)
{
cout << res.front() << ' ';
res.pop();
}
cout << res.front();
}
循环队列
#include <iostream>
#include <queue>
#include <iomanip>
#include <vector>
using namespace std;
class qq
{
private:
vector<int> data;
int size;
int front;
int rear;
public:
qq(int k)
{
size = k;
data.resize(k);
front = -1;
rear = -1;
}
bool enQueue(int value)
{
if (isFull())
{
return false;
}
if (isEmpty())
{
front = 0;
}
rear = (rear + 1) % size;
data[rear] = value;
return true;
}
bool deQueue()
{
if (isEmpty())
{
return false;
}
if (front == rear)
{
front = -1;
rear = -1;
}
else
{
front = (front + 1) % size;
}
return true;
}
int Front()
{
if (isEmpty())
{
return -1;
}
return data[front];
}
int Rear()
{
if (isEmpty())
{
return -1;
}
return data[rear];
}
bool isEmpty()
{
return front == -1;
}
bool isFull()
{
return (rear + 1) % size == front;
}
};
int main()
{
int t;
cin >> t;
int sz;
cin >> sz;
qq q(sz);
string c;
while (t--)
{
cin >> c;
if (c == "enQueue")
{
cin >> sz;
if (q.enQueue(sz))
{
cout << "true\n";
}
else
cout << "false\n";
}
if (c == "Rear")
{
cout << q.Rear() << "\n";
}
if (c == "Front")
{
cout << q.Front() << "\n";
}
if (c == "isFull")
{
if (q.isFull())
{
cout << "true\n";
}
else
cout << "false\n";
}
if (c == "deQueue")
{
if (q.deQueue())
{
cout << "true\n";
}
else
cout << "false\n";
}
if (c == "isEmpty")
{
if (q.isEmpty())
{
cout << "true\n";
}
else
cout << "false\n";
}
}
return 0;
}
kmp算法
#include <iostream>
#include <string>
#include <vector>
using namespace std;
// 计算模式串的next数组
vector<int> getNext(string pat)
{
int m = pat.size(); // 模式串的长度
vector<int> next(m); // next数组
next[0] = -1; // next[0]初始化为-1
int i = 0; // 模式串的前缀指针
int j = -1; // 模式串的后缀指针
while (i < m - 1)
{ // 遍历模式串
if (j == -1 || pat[i] == pat[j])
{ // 如果前后缀相等或者j为-1
i++; // 前缀指针后移
j++; // 后缀指针后移
next[i] = j; // 更新next[i]
}
else
{ // 如果前后缀不相等
j = next[j]; // 后缀指针回退
}
}
return next; // 返回next数组
}
// 在主串中查找模式串
int kmp(string txt, string pat)
{
vector<int> next = getNext(pat);
int n = txt.size(), i = 0, m = pat.size(), j = 0;
while (j < m && i < n)
{
if (j == -1 || txt[i] == pat[j])
{
i++;
j++;
}
else {
j = next[j];
}
}
if (j == m)
return i - j;
else return -1;
}
int main()
{
int t; // 实例的个数
cin >> t; // 输入实例的个数
for (int i = 0; i < t; i++)
{ // 对每个实例进行处理
string txt, pat; // 主串和模式串
cin >> txt >> pat; // 输入主串和模式串
vector<int> next = getNext(pat); // 计算模式串的next数组
cout << "next数组为:"; // 输出next数组
for (int j = 0; j < next.size(); j++)
{
cout << next[j] << " ";
}
cout << endl;
int res = kmp(txt, pat); // 在主串中查找模式串
cout << "匹配位置为:" << res << endl; // 输出匹配位置
}
return 0;
}
DS串应用–串替换
Time Limit: 1 Sec Memory Limit: 128 Mb Submitted: 11 Solved: 10
Description
给出主串、模式串、替换串,用KMP算法找出模式串在主串的位置,然后用替换串的字符替换掉模式串
本题只考虑一处替换的情况,如果你想做的完美一些,能够实现多处替换那可能需要考虑模式串和替换串长度不一致的情况
Input
第一个输入t,表示有t个实例
第二行输入第1个实例的主串,第三行输入第1个实例的模式串,第四行输入第1个实例的替换串
以此类推
Output
第一行输出第1个实例的主串
第二行输出第1个实例的主串替换后结果,如果没有发生替换就输出主串原来的内容。
以此类推
#include <iostream>
#include <string>
#include <vector>
using namespace std;
vector<int> getNext(string pat)
{
int m = pat.size();
vector<int> next(m);
next[0] = -1;
int i = 0;
int j = -1;
while (i < m - 1)
{
if (j == -1 || pat[i] == pat[j])
{
i++;
j++;
next[i] = j;
}
else
{
j = next[j];
}
}
return next;
}
int kmp(string txt, string pat)
{
vector<int> next = getNext(pat);
int n = txt.size(), i = 0, m = pat.size(), j = 0;
while (j < m && i < n)
{
if (j == -1 || txt[i] == pat[j])
{
i++;
j++;
}
else {
j = next[j];
}
}
if (j == m)
return i - j;
else return -1;
}
int main()
{
int t;
cin >> t;
for (int i = 0; i < t; i++)
{
string txt, pat,rep;
cin >> txt >> pat>>rep;
int res = kmp(txt, pat);
cout << txt<<endl;
if (res == -1)
{
cout << txt;
}
else
{
int j = 0;
for (; j < res; j++)
{
cout << txt[j];
}
cout << rep;
for (j += pat.size() ; j < txt.size(); j++)
{
cout << txt[j];
}
}
cout << endl;
}
return 0;
}
/**********************************************************************
Problem: 1072
Language: C++
Result: AC
Time:7 ms
Memory:2224 kb
**********************************************************************/
串应用- 计算一个串的最长的真前后缀
Time Limit: 1 Sec Memory Limit: 128 Mb Submitted: 12 Solved: 6
Description
给定一个串,如ABCDAB,则 - ABCDAB的真前缀有:{ A, AB,ABC, ABCD, ABCDA }
- ABCDAB的真后缀有:{ B, AB,DAB, CDAB, BCDAB }
因此,该串的真前缀和真后缀中最长的相等串为AB,我们称之为该串的“最长的真前后缀”。 试实现一个函数string matched_Prefix_Postfix(string str)
,得到输入串str的最长的真前后缀。若不存在最长的真前后缀则输出empty
Input
第1行:串的个数 n 第2行到第n+1行:n个字符串
Output
n个最长的真前后缀,若不存在最长的真前后缀则输出empty。
#include <iostream>
#include <string>
#include <vector>
using namespace std;
vector<int> getNext(string pat)
{
int m = pat.size();
vector<int> next(m);
next[0] = -1;
int i = 0;
int j = -1;
while (i < m - 1)
{
if (j == -1 || pat[i] == pat[j])
{
i++;
j++;
next[i] = j;
}
else
{
j = next[j];
}
}
return next;
}
int kmp(string txt, string pat)
{
vector<int> next = getNext(pat);
int n = txt.size(), i = 0, m = pat.size(), j = 0;
while (j < m && i < n)
{
if (j == -1 || txt[i] == pat[j])
{
i++;
j++;
}
else {
j = next[j];
}
}
if (j == m)
return i - j;
else return -1;
}
int main()
{
int t;
cin >> t;
while (t--)
{
string c;
cin >> c;
bool flag = 0;
for (int i = c.size() - 1;i >0 ;i--)
{
string qian(c, 0, i);
string hou(c, c.size() - i, i);
if (qian == hou)
{
cout << qian;
flag = 1;
break;
}
}
if (flag == 0)
{
cout << "empty";
}
cout << endl;
}
return 0;
}
/**********************************************************************
Problem: 1073
Language: C++
Result: AC
Time:8 ms
Memory:2224 kb
**********************************************************************/
DS串应用—最长重复子串
Time Limit: 1 Sec Memory Limit: 128 Mb Submitted: 7 Solved: 1
Description
求串的最长重复子串长度(子串不重叠)。例如:abcaefabcabc的最长重复子串是串abca,长度为4。
Input
测试次数t
t个测试串
Output
对每个测试串,输出最长重复子串长度,若没有重复子串,输出-1.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
vector<int> getNext(string pat)
{
int m = pat.size();
vector<int> next(m);
next[0] = -1;
int i = 0;
int j = -1;
while (i < m - 1)
{
if (j == -1 || pat[i] == pat[j])
{
i++;
j++;
next[i] = j;
}
else
{
j = next[j];
}
}
return next;
}
int kmp(string txt, string pat)
{
vector<int> next = getNext(pat);
int n = txt.size(), i = 0, m = pat.size(), j = 0;
while (j < m && i < n)
{
if (j == -1 || txt[i] == pat[j])
{
i++;
j++;
}
else {
j = next[j];
}
}
if (j == m)
return i - j;
else return -1;
}
int main()
{
int t;
cin >> t;
while (t--)
{
string c,z;
z = " ";
int f = 0;
cin >> c;
int l = c.size() / 2+1;
while (l--)
{
if (l == 0)
break;
for (int i = 0;i < c.size()-l+1;i += l)
{
string p(c, i, l);
string s(c, 0, i),w(c,i+l,c.size()-i-l);
string txt=s+ w;
if (kmp(txt, p) != -1)
{
f = 1;
break;
}
}
if (f == 1)
{
break;
}
}
if (f == 1)
cout << l << endl;
else cout << -1 << endl;
}
return 0;
}
/**********************************************************************
Problem: 1074
Language: C++
Result: AC
Time:7 ms
Memory:2224 kb
**********************************************************************/
子串循环问题 (Ver. I)
Time Limit: 1 Sec Memory Limit: 128 Mb Submitted: 2 Solved: 1
Description
给定一个字符串,求需要添加至少几个字符到字符串末尾才能使得整个字符串由某一个不为本身的子串循环构成? 如“abca”,添加“bc”后构成“abcabc”,其由子串“abc”循环构成;也可以添加“abca”后构成“abcaabca”,其由子串“abca”循环构成,相比之下“bc”只有2个字符,添加的字符量最少。
Input
第一行包括一个整数T(1 <= T <= 100)
,代表测试组数
每组测试数据包括一行字符串,其长度范围为 [3, 10^4]
Output
对于每组测试数据
输出一个整数N,代表添加的最小字符数量
#include <iostream>
#include <string>
#include <vector>
using namespace std;
vector<int> getNext(string pat)
{
int m = pat.size();
vector<int> next(m+1);
next[0] = -1;
int i = 0;
int j = -1;
while (i < m )
{
if (j == -1 || pat[i] == pat[j])
{
i++;
j++;
next[i] = j;
}
else
{
j = next[j];
}
}
return next;
}
int main()
{
int t;
cin >> t;
while (t--)
{
string p;
cin >> p;
vector<int> next = getNext(p);
int len = p.size();
int clen = len - next[len];
int uplen = clen - len % clen;
if (clen != len && len % clen == 0)
uplen = 0;
cout << uplen << endl;
}
return 0;
}
树
二叉树
DS二叉树—二叉树构建与遍历
Time Limit: 1 Sec Memory Limit: 128 Mb Submitted: 1 Solved: 1
Description
给定一颗二叉树的逻辑结构如下图,(先序遍历的结果,空树用字符‘#’表示,例如AB#C##D##),建立该二叉树的二叉链式存储结构,并输出该二叉树的先序遍历、中序遍历和后序遍历结果。
A
/ \
B D
\
C
Input
第一行输入一个整数t,表示有t个二叉树
第二行起输入每个二叉树的先序遍历结果,空树用字符‘#’表示,连续输入t行。
Output
输出每个二叉树的先序遍历、中序遍历和后序遍历结果。
Sample
Input
2
AB#C##D##
AB##C##
Output
ABCD
BCAD
CBDA
ABC
BAC
BCA
#include <iostream>
#include <string>
using namespace std;
struct TreeNode {
char data;
TreeNode* left;
TreeNode* right;
TreeNode(char val) : data(val), left(nullptr), right(nullptr)
{}
};
TreeNode* buildTree(string p, int& index) {
if (index >= p.size()) {
return nullptr;
}
char val = p[index++];
if (val == '#') {
return nullptr;
}
TreeNode* root = new TreeNode(val);
root->left = buildTree(p, index);
root->right = buildTree(p, index);
return root;
}
void xianbian(TreeNode* root) {
if (root) {
cout << root->data;
xianbian(root->left);
xianbian(root->right);
}
}
void zhongbian(TreeNode* root) {
if (root) {
zhongbian(root->left);
cout << root->data;
zhongbian(root->right);
}
}
void houbian(TreeNode* root) {
if (root) {
houbian(root->left);
houbian(root->right);
cout << root->data;
}
}
int main() {
int t;
cin >> t;
for (int i = 0; i < t; i++) {
string p;
cin >> p;
int index = 0;
TreeNode* root = buildTree(p, index);
xianbian(root);
cout << endl;
zhongbian(root);
cout << endl;
houbian(root);
cout << endl;
}
return 0;
}
DS二叉树–叶子数量
Time Limit: 1 Sec Memory Limit: 128 Mb Submitted: 1 Solved: 1
Description
计算一颗二叉树包含的叶子结点数量。
提示:叶子是指它的左右孩子为空。
建树方法采用“先序遍历+空树用0表示”的方法,即给定一颗二叉树的先序遍历的结果为AB0C00D00,其中空节点用字符‘0’表示。则该树的逻辑结构如下。
A
/ \
B D
\
C
Input
第一行输入一个整数t,表示有t个测试数据
第二行起输入二叉树先序遍历的结果,空树用字符‘0’表示,输入t行
Output
逐行输出每个二叉树的包含的叶子数量
Sample
Input
Copy
3
AB0C00D00
AB00C00
ABC00D00E00
Output
Copy
2
2
3
#include <iostream>
#include <string>
using namespace std;
int jie = 0;
struct TreeNode {
char data;
TreeNode* left;
TreeNode* right;
TreeNode(char val) : data(val), left(nullptr), right(nullptr)
{}
};
TreeNode* buildTree(string p, int& index) {
if (index >= p.size()) {
return nullptr;
}
char val = p[index++];
if (val == '0') {
return nullptr;
}
int f = 0;
TreeNode* root = new TreeNode(val);
root->left = buildTree(p, index);
// if (root->left != nullptr)
// {
// f = 1;
// cout << " " << root->left->data << endl;
// }
root->right = buildTree(p, index);
if (root->left == nullptr && root->right == nullptr)
{
jie++;
}
// if (root->right != nullptr)
// {
// f = 1;
// cout << " " << root->right->data << endl;
// }
// if (f == 1)
// {
// jie++;
// cout << root->left <<" "<< root->left << endl;
// }
return root;
}
void xianbian(TreeNode* root) {
if (root) {
cout << root->data;
xianbian(root->left);
xianbian(root->right);
}
}
void zhongbian(TreeNode* root) {
if (root) {
zhongbian(root->left);
cout << root->data;
zhongbian(root->right);
}
}
void houbian(TreeNode* root) {
if (root) {
houbian(root->left);
houbian(root->right);
cout << root->data;
}
}
int main() {
int t;
cin >> t;
for (int i = 0; i < t; i++) {
jie = 0;
string p;
cin >> p;
int index = 0;
TreeNode* root = buildTree(p, index);
cout << jie << endl;
}
return 0;
}
DS二叉树–左叶子数量
Time Limit: 1 Sec Memory Limit: 128 Mb Submitted: 1 Solved: 0
Description
计算一颗二叉树包含的叶子结点数量。
左叶子是指它的左右孩子为空,而且它是父亲的左孩子
提示:可以用三叉链表法,也可以用现有算法对两层结点进行判断
建树方法采用“先序遍历+空树用0表示”的方法
Input
第一行输入一个整数t,表示有t个测试数据
第二行起输入二叉树先序遍历的结果,空树用字符‘0’表示,输入t行
Output
逐行输出每个二叉树的包含的左叶子数量
Sample
Input
Copy
3
AB0C00D00
AB00C00
ABCD0000EF000
Output
Copy
0
1
2
#include <iostream>
#include <string>
using namespace std;
int jie = 0;
struct TreeNode {
char data;
TreeNode* left;
TreeNode* right;
TreeNode(char val) : data(val), left(nullptr), right(nullptr)
{}
};
TreeNode* buildTree(string p, int& index) {
if (index >= p.size()) {
return nullptr;
}
char val = p[index++];
if (val == '0') {
return nullptr;
}
TreeNode* root = new TreeNode(val);
root->left = buildTree(p, index);
root->right = buildTree(p, index);
return root;
}
void xianbian(TreeNode* root) {
if (root) {
//cout << root->data;
xianbian(root->left);
if (root->left != nullptr)
{
if (root->left->left == nullptr && root->left->right == nullptr)
{
jie++;
}
}
xianbian(root->right);
}
}
void zhongbian(TreeNode* root) {
if (root) {
zhongbian(root->left);
cout << root->data;
zhongbian(root->right);
}
}
void houbian(TreeNode* root) {
if (root) {
houbian(root->left);
houbian(root->right);
cout << root->data;
}
}
int main() {
int t;
cin >> t;
for (int i = 0; i < t; i++) {
jie = 0;
string p;
cin >> p;
int index = 0;
TreeNode* root = buildTree(p, index);
xianbian(root);
cout << jie << endl;
}
return 0;
}
DS二叉树——二叉树之父子结点
Time Limit: 1 Sec Memory Limit: 128 Mb Submitted: 2 Solved: 0
Description
给定一颗二叉树的逻辑结构,(先序遍历的结果,空树用字符‘0’表示,例如AB0C00D00),建立该二叉树的二叉链式存储结构。
编写程序输出该树的所有叶子结点和它们的父亲结点
Input
第一行输入一个整数t,表示有t个二叉树
第二行起,按照题目表示的输入方法,输入每个二叉树的先序遍历,连续输入t行
Output
第一行按先序遍历,输出第1个示例的叶子节点
第二行输出第1个示例中与叶子相对应的父亲节点
以此类推输出其它示例的结果
Sample
Input
Copy
3
AB0C00D00
AB00C00
ABCD0000EF000
Output
Copy
C D
B A
B C
A A
D F
C E
#include <iostream>
#include <string>
using namespace std;
int jie = 0;
struct TreeNode {
char data;
TreeNode* left;
TreeNode* right;
TreeNode(char val) : data(val), left(nullptr), right(nullptr)
{}
};
TreeNode* buildTree(string p, int& index) {
if (index >= p.size()) {
return nullptr;
}
char val = p[index++];
if (val == '0') {
return nullptr;
}
TreeNode* root = new TreeNode(val);
root->left = buildTree(p, index);
root->right = buildTree(p, index);
return root;
}
void xianbian(TreeNode* root) {
if (root) {
//cout << root->data;
xianbian(root->left);
xianbian(root->right);
}
}
void zhongbian(TreeNode* root) {
if (root) {
zhongbian(root->left);
zhongbian(root->right);
}
}
void houbian(TreeNode* root) {
if (root) {
houbian(root->left);
houbian(root->right);
cout << root->data;
}
}
void find1(TreeNode* p)
{
if (p)
{
if (!p->left && !p->right)
cout << p->data << ' ';
find1(p->left);
find1(p->right);
}
}
void find2(TreeNode* p)
{
if (p)
{
if (p->left)
{
if (!p->left->left && !p->left->right)
cout << p->data << ' ';
}
find2(p->left);
if (p->right)
{
if (!p->right->right && !p->right->left)
cout << p->data << ' ';
}
find2(p->right);
}
}
int main() {
int t;
cin >> t;
for (int i = 0; i < t; i++) {
jie = 0;
string p;
cin >> p;
int index = 0;
TreeNode* root = buildTree(p, index);
find1(root);
cout << endl;
find2(root);
cout << endl;
}
return 0;
}
DS二叉树——二叉树之数组存储
Submit Page TestData Time Limit: 1 Sec Memory Limit: 128 Mb Submitted: 4 Solved: 2
Description
二叉树可以采用数组的方法进行存储,把数组中的数据依次自上而下,自左至右存储到二叉树结点中,一般二叉树与完全二叉树对比,比完全二叉树缺少的结点就在数组中用0来表示。如下图所示
结点存储的数据均为非负整数
Input
第一行输入一个整数t,表示有t个二叉树
第二行起,每行输入一个数组,先输入数组长度,再输入数组内数据,每个数据之间用空格隔开,输入的数据都是非负整数
连续输入t行
Output
每行输出一个示例的先序遍历结果,每个结点之间用空格隔开
Sample
Input
Copy
3
3 1 2 3
5 1 2 3 0 4
13 1 2 3 4 0 5 6 7 8 0 0 9 10
Output
Copy
1 2 3
1 2 4 3
1 2 4 7 8 3 5 9 10 6
#include <iostream>
#include <string>
using namespace std;
int jie = 0;
int t;
int* c = new int[t];
struct TreeNode
{
char data;
TreeNode* left;
TreeNode* right;
TreeNode(char val) : data(val), left(nullptr), right(nullptr)
{
}
};
TreeNode* buildTree(string p, int& index)
{
if (index >= p.size())
{
return nullptr;
}
char val = p[index++];
if (val == '0')
{
return nullptr;
}
TreeNode* root = new TreeNode(val);
root->left = buildTree(p, index);
root->right = buildTree(p, index);
return root;
}
void xianbian(TreeNode* root)
{
if (root)
{
// cout << root->data;
xianbian(root->left);
xianbian(root->right);
}
}
void zhongbian(TreeNode* root)
{
if (root)
{
zhongbian(root->left);
zhongbian(root->right);
}
}
void houbian(TreeNode* root)
{
if (root)
{
houbian(root->left);
houbian(root->right);
cout << root->data;
}
}
void find1(TreeNode* p)
{
if (p)
{
if (!p->left && !p->right)
cout << p->data << ' ';
find1(p->left);
find1(p->right);
}
}
void find2(TreeNode* p)
{
if (p)
{
if (p->left)
{
if (!p->left->left && !p->left->right)
cout << p->data << ' ';
}
find2(p->left);
if (p->right)
{
if (!p->right->right && !p->right->left)
cout << p->data << ' ';
}
find2(p->right);
}
}
void print(int index)
{
if (c[index] && index < t)
{
cout << c[index] << " " ;
print(2 * index + 1);
print(2 * index + 2);
}
}
int main()
{
int n;
cin >> n;
while (n--)
{
cin >> t;
for (int i = 0; i < t; i++)
{
cin >> c[i];
}
print(0);
cout << endl;
}
return 0;
}
DS二叉树–层次遍历
Time Limit: 1 Sec Memory Limit: 128 Mb Submitted: 7 Solved: 5
Description
层次遍历二叉树,是从根结点开始遍历,按层次次序“自上而下,从左至右”访问树中的各结点。
建树方法采用“先序遍历+空树用0表示”的方法
采用队列实现
Input
第一行输入一个整数t,表示有t个测试数据
第二行起输入二叉树先序遍历的结果,空树用字符‘0’表示,输入t行
Output
逐行输出每个二叉树的层次遍历结果
Sample
Input
Copy
2
AB0C00D00
ABCD00E000FG00H0I00
Output
Copy
ABDC
ABFCGHDEI
#include <iostream>
#include <string>
using namespace std;
struct TreeNode {
char data;
TreeNode* left;
TreeNode* right;
TreeNode(char val) : data(val), left(nullptr), right(nullptr)
{}
};
TreeNode* buildTree(string p, int& index) {
if (index >= p.size()) {
return nullptr;
}
char val = p[index++];
if (val == '0') {
return nullptr;
}
TreeNode* root = new TreeNode(val);
root->left = buildTree(p, index);
root->right = buildTree(p, index);
return root;
}
void xianbian(TreeNode* root) {
if (root) {
cout << root->data;
xianbian(root->left);
xianbian(root->right);
}
}
void zhongbian(TreeNode* root) {
if (root) {
zhongbian(root->left);
cout << root->data;
zhongbian(root->right);
}
}
void houbian(TreeNode* root) {
if (root) {
houbian(root->left);
houbian(root->right);
cout << root->data;
}
}
int high(struct TreeNode* root)
{
int h1, h2;
if (root)
{
h1 = high(root->left);
h2 = high(root->right);
return h1 > h2 ? h1 + 1 : h2 + 1;
}
else return 0;
}
void printh(struct TreeNode* root,int h,int w)
{
w++;
if (root)
{
if (root->left != nullptr)
{
if (w == h)
{
cout << root->left->data;
}
printh(root->left, h,w);
}
if (root->right != nullptr)
{
if (w == h)
{
cout << root->right->data;
}
printh(root->right, h,w);
}
}
}
int main() {
int t;
cin >> t;
int w = 1;
while(t--) {
string p;
cin >> p;
int index = 0;
TreeNode* root = buildTree(p, index);
int h = high(root);
//cout << h << "\n";
cout << root->data;
for (int i = 1;i <= h;i++)
{
printh(root, i,1);
}
cout << "\n";
}
return 0;
}
DS二叉树—二叉树镜面反转
Time Limit: 1 Sec Memory Limit: 128 Mb Submitted: 8 Solved: 5
Description
假设二叉树用二叉链表存储,用先序序列结果创建。输入二叉树的先序序列,请你先创建二叉树,并对树做个镜面反转,再输出反转后的二叉树的先序遍历、中序遍历、后序遍历和层序遍历的序列。所谓镜面反转,是指将所有非叶结点的左右孩子对换。
–程序要求–
- 若使用C++只能include一个头文件
iostream
;若使用C语言只能include一个头文件stdio.h
- 程序中若include多过一个头文件,不看代码,作0分处理
- 不允许使用第三方对象或函数实现本题的要求
Input
t
组测试数据
每组测试数据是一个二叉树的先序遍历序列,#
表示空树
Output
对每棵二叉树,输出镜面反转后的先序、中序、后序和层次遍历序列。如果空树,输出四个NULL(后面不加空格)。如下:
NULL
NULL
NULL
NULL
Sample
Input
Copy
3
41#32###65##7##
AB#C##D##
AB##C##
Output
Copy
4 6 7 5 1 3 2
7 6 5 4 3 2 1
7 5 6 2 3 1 4
4 6 1 7 5 3 2
A D B C
D A C B
D C B A
A D B C
A C B
C A B
C B A
A C B
#include <iostream>
#include <string>
using namespace std;
struct TreeNode {
char data;
TreeNode* left;
TreeNode* right;
TreeNode(char val) : data(val), left(nullptr), right(nullptr)
{}
};
TreeNode* buildTree(string p, int& index) {
if (index >= p.size()) {
return nullptr;
}
char val = p[index++];
if (val == '#') {
return nullptr;
}
TreeNode* root = new TreeNode(val);
root->right = buildTree(p, index);
root->left = buildTree(p, index);//直接构建时调换顺序即可
return root;
}
void xianbian(TreeNode* root) {
if (root) {
cout << root->data << " ";
xianbian(root->left);
xianbian(root->right);
}
}
void zhongbian(TreeNode* root) {
if (root) {
zhongbian(root->left);
cout << root->data << " ";
zhongbian(root->right);
}
}
void houbian(TreeNode* root) {
if (root) {
houbian(root->left);
houbian(root->right);
cout << root->data << " ";
}
}
int high(struct TreeNode* root)
{
int h1, h2;
if (root)
{
h1 = high(root->left);
h2 = high(root->right);
return h1 > h2 ? h1 + 1 : h2 + 1;
}
else return 0;
}
void printh(struct TreeNode* root, int h, int w)
{
w++;
if (root)
{
if (root->left != nullptr)
{
if (w == h)
{
cout << root->left->data << " ";
}
printh(root->left, h, w);
}
if (root->right != nullptr)
{
if (w == h)
{
cout << root->right->data << " ";
}
printh(root->right, h, w);
}
}
}
void cengbian(TreeNode* root)
{
int h = high(root);
cout << root->data << " ";
for (int i = 1;i <= h;i++)
{
printh(root, i, 1);
}
cout << "\n";
}
int main() {
int t;
cin >> t;
int w = 1;
while (t--) {
string p;
cin >> p;
int index = 0;
TreeNode* root = buildTree(p, index);
xianbian(root);
cout << "\n";
zhongbian(root);
cout << "\n";
houbian(root);
cout << "\n";
cengbian(root);
cout << "\n";
}
return 0;
}
DS二叉树_伪层序遍历构建二叉树
Time Limit: 1 Sec Memory Limit: 128 Mb Submitted: 93 Solved: 40
Description
给定一个用于表示二叉树的一维数组,该数组长度为n。该数组是按照一种类似于层序遍历的方式表示二叉树的,用数字-1表示某个结点为空。
根据给定的一维数组,构建二叉树并依次输出该二叉树的前序、中序、后序遍历。
Input
第一行输入t,表示有t个测试样例。
第二行起,每一行首先输入一个正整数n,接下来依次输入n个整数。
以此类推,共输入t个测试样例。
Output
每三行依次输出每个二叉树的前序、中序、后序遍历。
共输出t个二叉树。
注意输出末尾的空格。
Sample
Input
Copy
4
5 1 -1 2 3 4
7 1 2 2 3 4 4 3
7 1 2 2 -1 3 -1 3
7 1 2 -1 3 -1 4 -1
Output
Copy
1 2 3 4
1 3 2 4
3 4 2 1
1 2 3 4 2 4 3
3 2 4 1 4 2 3
3 4 2 4 3 2 1
1 2 3 2 3
2 3 1 2 3
3 2 3 2 1
1 2 3 4
4 3 2 1
4 3 2 1
#include <iostream>
#include <string>
#include <queue>
using namespace std;
struct TreeNode {
int data;
TreeNode* left;
TreeNode* right;
TreeNode(char val) : data(val), left(nullptr), right(nullptr)
{}
};
TreeNode* buildTree(vector<int> nodes) {
if (nodes.empty() || nodes[0] == -1) {
return nullptr;
}
TreeNode* root = new TreeNode(nodes[0]);
queue<TreeNode*> nodeQueue;
nodeQueue.push(root);
int i = 1;
while (i < nodes.size()) {
TreeNode* node = nodeQueue.front();
nodeQueue.pop();
if (nodes[i] != -1) {
node->left = new TreeNode(nodes[i]);
nodeQueue.push(node->left);
}
i++;
if (i < nodes.size() && nodes[i] != -1) {
node->right = new TreeNode(nodes[i]);
nodeQueue.push(node->right);
}
i++;
}
return root;
}
// TreeNode* buildTree(string p, int& index) {
// if (index >= p.size()) {
// return nullptr;
// }
// char val = p[index++];
// if (val == '#') {
// return nullptr;
// }
// TreeNode* root = new TreeNode(val);
// root->left = buildTree(p, index);
// root->right = buildTree(p, index);
// return root;
// }
void xianbian(TreeNode* root) {
if (root) {
cout << root->data<<" ";
xianbian(root->left);
xianbian(root->right);
}
}
void zhongbian(TreeNode* root) {
if (root) {
zhongbian(root->left);
cout << root->data<<" ";
zhongbian(root->right);
}
}
void houbian(TreeNode* root) {
if (root) {
houbian(root->left);
houbian(root->right);
cout << root->data<<" ";
}
}
int main() {
int t;
cin >> t;
for (int i = 0; i < t; i++) {
int x;
cin >> x;
vector<int> p(x);
for(int j=0;j<x;j++)
{
cin>>p[j];
}
int index = 0;
TreeNode* root = buildTree(p);
xianbian(root);
cout << endl;
zhongbian(root);
cout << endl;
houbian(root);
cout << endl;
cout << endl;
}
return 0;
}
DS二叉树_对称二叉树
Time Limit: 1 Sec Memory Limit: 128 Mb Submitted: 30 Solved: 19
description
给定二叉树,检查该二叉树是否为镜像对称的。
Input
第一行输入t,表示有t个测试样例。
第二行起,每一行首先输入n,接着输入n个整数代表一个二叉树。
依次输入t个二叉树。
数组形式的二叉树表示方法与题目:DS二叉树_伪层序遍历构建二叉树 相同,输入-1表示空结点。
Output
每一行输出二叉树是否为镜像对称。
依次输出t行。
Sample
Input
Copy
4
7 1 2 2 3 4 4 3
7 1 2 2 -1 3 -1 3
7 10 20 20 -1 40 40 -1
5 1 2 2 -1 3
Output
Copy
true
false
true
false
Hint
结点个数 >= 1
n >= 1
1 <= 结点值 <= 1000
#include <iostream>
#include <string>
#include <queue>
using namespace std;
string xian, hou;
struct TreeNode
{
int data;
TreeNode *left;
TreeNode *right;
TreeNode(char val) : data(val), left(nullptr), right(nullptr)
{
}
};
TreeNode *buildTree(vector<int> nodes)
{
if (nodes.empty() || nodes[0] == -1)
{
return nullptr;
}
TreeNode *root = new TreeNode(nodes[0]);
queue<TreeNode *> nodeQueue;
nodeQueue.push(root);
int i = 1;
while (i < nodes.size())
{
TreeNode *node = nodeQueue.front();
nodeQueue.pop();
if (nodes[i] != -1)
{
node->left = new TreeNode(nodes[i]);
nodeQueue.push(node->left);
}
i++;
if (i < nodes.size() && nodes[i] != -1)
{
node->right = new TreeNode(nodes[i]);
nodeQueue.push(node->right);
}
i++;
}
return root;
}
// TreeNode* buildTree(string p, int& index) {
// if (index >= p.size()) {
// return nullptr;
// }
// char val = p[index++];
// if (val == '#') {
// return nullptr;
// }
// TreeNode* root = new TreeNode(val);
// root->left = buildTree(p, index);
// root->right = buildTree(p, index);
// return root;
// }
void xianbian(TreeNode *root)
{
if (root)
{
xian += '0' + root->data;
xianbian(root->left);
xianbian(root->right);
}
}
void zhongbian(TreeNode *root)
{
if (root)
{
zhongbian(root->left);
cout << root->data << " ";
zhongbian(root->right);
}
}
void houbian(TreeNode *root)
{
if (root)
{
houbian(root->left);
houbian(root->right);
hou += '0' + root->data;
}
}
bool isMirror(TreeNode *node1, TreeNode *node2)
{
if (node1 == nullptr && node2 == nullptr)
{
return true;
}
if (node1 == nullptr || node2 == nullptr)
{
return false;
}
return (node1->data == node2->data) && isMirror(node1->right, node2->left) && isMirror(node1->left, node2->right);
}
int main()
{
int t;
cin >> t;
for (int i = 0; i < t; i++)
{
int x;
cin >> x;
vector<int> p(x);
xian = "";
hou = "";
for (int j = 0; j < x; j++)
{
cin >> p[j];
}
TreeNode *root = buildTree(p);
if(isMirror(root->left,root->right)){
cout<<"true"<<endl;
}
else{
cout<<"false"<<endl;
}
}
return 0;
}
DS二叉树–赫夫曼树的构建与编码
Time Limit: 1 Sec Memory Limit: 128 Mb Submitted: 10 Solved: 9
Description
给定n个权值,根据这些权值构造huffman树,并进行huffman编码
参考课本算法,注意数组访问是从位置1开始
要求:赫夫曼的构建中,默认左孩子权值不大于右孩子权值
Input
第一行输入t,表示有t个测试实例 第二行先输入n,表示第1个实例有n个权值,接着输入n个权值,权值全是小于1万的正整数 依此类推
Output
逐行输出每个权值对应的编码,格式如下:权值-编码 即每行先输出1个权值,再输出一个短划线,再输出对应编码,接着下一行输入下一个权值和编码。 以此类推
Sample
Input
Copy
1
5 15 4 4 3 2
Output
Copy
15-1
4-010
4-011
3-001
2-000
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
const int MaxW = 9999999;
class HuffNode
{
public:
int weight;
int parent;
int leftchild;
int rightchild;
};
class HuffMan
{
private:
void MakeTree();
void SelectMin(int pos, int *s1, int *s2);
public:
int len;
int lnum;
HuffNode *huffTree;
string *huffCode;
void MakeTree(int n, int wt[]);
void Coding();
void Destroy();
};
void HuffMan::MakeTree(int n, int wt[])
{
int i;
lnum = n;
len = 2 * n - 1;
huffTree = new HuffNode[2 * n];
huffCode = new string[lnum + 1];
for (i = 1; i <= n; i++)
huffTree[i].weight = wt[i - 1];
for (i = 1; i <= len; i++)
{
if (i > n)
huffTree[i].weight = 0;
huffTree[i].parent = 0;
huffTree[i].leftchild = 0;
huffTree[i].rightchild = 0;
}
MakeTree();
}
void HuffMan::SelectMin(int pos, int *s1, int *s2)
{
int w1, w2, i;
w1 = w2 = MaxW;
*s1 = *s2 = 0;
for (i = 1; i <= pos; i++)
{
if (huffTree[i].parent == 0 && huffTree[i].weight < w1)
{
w2 = w1;
*s2 = *s1;
w1 = huffTree[i].weight;
*s1 = i;
}
else if (huffTree[i].parent == 0 && huffTree[i].weight < w2)
{
w2 = huffTree[i].weight;
*s2 = i;
}
}
}
void HuffMan::MakeTree()
{
int i, s1, s2;
for (i = lnum + 1; i <= len; i++)
{
SelectMin(i - 1, &s1, &s2);
huffTree[s1].parent = i;
huffTree[s2].parent = i;
huffTree[i].leftchild = s1;
huffTree[i].rightchild = s2;
huffTree[i].weight = huffTree[s1].weight + huffTree[s2].weight;
}
}
void HuffMan::Destroy()
{
len = 0;
lnum = 0;
delete[] huffTree;
delete[] huffCode;
}
void HuffMan::Coding()
{
char *cd;
int i, c, f, start;
cd = new char[lnum];
cd[lnum - 1] = '\0';
for (i = 1; i <= lnum; ++i)
{
start = lnum - 1;
for (c = i, f = huffTree[i].parent; f != 0; c = f, f = huffTree[f].parent)
{
if (huffTree[f].leftchild == c)
cd[--start] = '0';
else
cd[--start] = '1';
}
huffCode[i].assign(&cd[start]);
}
delete[] cd;
}
int main()
{
int t, n, i, j;
int wt[800];
HuffMan myHuff;
cin >> t;
for (i = 0; i < t; i++)
{
cin >> n;
for (j = 0; j < n; j++)
{
cin >> wt[j];
}
myHuff.MakeTree(n, wt);
myHuff.Coding();
for (j = 1; j <= n; j++)
{
cout << myHuff.huffTree[j].weight << '-';
cout << myHuff.huffCode[j] << endl;
}
myHuff.Destroy();
}
return 0;
}
DS二叉树–赫夫曼树解码(含代码框架)
Time Limit: 1 Sec Memory Limit: 128 Mb Submitted: 6 Solved: 5
Description
已知赫夫曼编码算法和程序,在此基础上进行赫夫曼解码
在赫夫曼树的类定义中增加了一个公有方法:
int Decode(const string codestr, char txtstr[]); //输入编码串codestr,输出解码串txtstr
该方法如果解码成功则返回1,解码失败则返回-1,本程序增加宏定义ok表示1,error表示-1
Input
第一行输入t,表示有t个测试实例
第二行先输入n,表示第1个实例有n个权值,接着输入n个权值,权值全是小于1万的正整数
第三行输入n个字母,表示与权值对应的字符
第四行输入k,表示要输入k个编码串
第五行起输入k个编码串
以此类推输入下一个示例
Output
每行输出解码后的字符串,如果解码失败直接输出字符串“error”,不要输出部分解码结果
Sample
Input
Copy
2
5 15 4 4 3 2
A B C D E
3
11111
10100001001
00000101100
4 7 5 2 4
A B C D
3
1010000
111011
111110111
Output
Copy
AAAAA
ABEAD
error
BBAAA
error
DCD
#include <iostream>
#include <string>
#include <cstring>
#include <vector>
using namespace std;
#define ok 1
#define error -1
const int MaxW = 9999999;
class HuffNode
{
public:
int weight;
int parent;
int leftchild;
int rightchild;
int zhao;
};
class HuffMan
{
private:
void MakeTree();
void SelectMin(int pos, int *s1, int *s2);
public:
int len;
int lnum;
HuffNode *huffTree;
string *huffCode;
void MakeTree(int n, int wt[], char ct[]);
void Coding();
void Destroy();
int Decode(const string codestr, char txtstr[]);
};
void HuffMan::MakeTree(int n, int wt[], char ct[])
{
int i;
lnum = n;
len = 2 * n - 1;
huffTree = new HuffNode[2 * n];
huffCode = new string[lnum + 1];
for (i = 1; i <= n; i++)
{
huffTree[i].weight = wt[i - 1];
huffTree[i].zhao = ct[i - 1];
}
huffTree[i].weight = wt[i - 1];
for (i = 1; i <= len; i++)
{
if (i > n)
{
huffTree[i].weight = 0;
huffTree[i].zhao = '0';
}
huffTree[i].parent = 0;
huffTree[i].leftchild = 0;
huffTree[i].rightchild = 0;
}
MakeTree();
}
void HuffMan::SelectMin(int pos, int *s1, int *s2)
{
int w1, w2, i;
w1 = w2 = MaxW;
*s1 = *s2 = 0;
for (i = 1; i <= pos; i++)
{
if (huffTree[i].parent == 0 && huffTree[i].weight < w1)
{
w2 = w1;
*s2 = *s1;
w1 = huffTree[i].weight;
*s1 = i;
}
else if (huffTree[i].parent == 0 && huffTree[i].weight < w2)
{
w2 = huffTree[i].weight;
*s2 = i;
}
}
}
void HuffMan::MakeTree()
{
int i, s1, s2;
for (i = lnum + 1; i <= len; i++)
{
SelectMin(i - 1, &s1, &s2);
huffTree[s1].parent = i;
huffTree[s2].parent = i;
huffTree[i].leftchild = s1;
huffTree[i].rightchild = s2;
huffTree[i].weight = huffTree[s1].weight + huffTree[s2].weight;
}
}
void HuffMan::Destroy()
{
len = 0;
lnum = 0;
delete[] huffTree;
delete[] huffCode;
}
void HuffMan::Coding()
{
char *cd;
int i, c, f, start;
cd = new char[lnum];
cd[lnum - 1] = '\0';
for (i = 1; i <= lnum; ++i)
{
start = lnum - 1;
for (c = i, f = huffTree[i].parent; f != 0; c = f, f = huffTree[f].parent)
{
if (huffTree[f].leftchild == c)
cd[--start] = '0';
else
cd[--start] = '1';
}
huffCode[i].assign(&cd[start]);
}
delete[] cd;
}
int HuffMan::Decode(const string codestr, char txtstr[])
{
int i, k, c;
char ch;
c = len;
k = 0;
for (i = 0; i < codestr.length(); i++)
{
ch = codestr[i];
if (ch == '0')
{
c = huffTree[c].leftchild;
}
else if (ch == '1')
{
c = huffTree[c].rightchild;
}
else if (ch != '0' && ch != '1')
{
return error;
}
if (huffTree[c].leftchild == 0 && huffTree[c].rightchild == 0)
{
txtstr[k] = huffTree[c].zhao;
k++;
c = len;
}
else
{
ch = '\0';
}
}
if (ch == '\0')
return error;
else
txtstr[k] = '\0';
return ok;
}
int main()
{
int t, n, i, j, k;
int wt[800];
char ct[800];
HuffMan myHuff;
cin >> t;
string codestr;
char txtstr[800];
for (i = 0; i < t; i++)
{
cin >> n;
for (j = 0; j < n; j++)
{
cin >> wt[j];
}
for (j = 0; j < n; j++)
{
cin >> ct[j];
}
myHuff.MakeTree(n, wt, ct);
myHuff.Coding();
cin >> k;
for (j = 0; j < k; j++)
{
cin >> codestr;
if (myHuff.Decode(codestr, txtstr) == 1)
{
cout << txtstr << endl;
}
else
{
cout << "error" << endl;
}
}
myHuff.Destroy();
}
return 0;
}
赫夫曼编码长度
Submit Page TestData Time Limit: 1 Sec Memory Limit: 128 Mb Submitted: 4 Solved: 3
Description
每行一个大小写英文字母组成的字符串,长度不大于 1000,通过前缀编码后最短的编码长度。
Input
每组数据一行,大小写英文字母
Output
每组数据输出赫夫曼编码长度
Sample
Input
3
AABBCCDEEEE
AAABCCC
BBACB
Output
25
11
7
#include <iostream>
#include <queue>
#include <vector>
#include <cstring>
using namespace std;
struct Node
{
int freq;
Node *left;
Node *right;
Node(int f) : freq(f), left(NULL), right(NULL) {}
};
struct compare
{
bool operator()(Node *l, Node *r)
{
return l->freq > r->freq;
}
};
int howlength(string str)
{
int freq[256] = {0};
for (char c : str)
{
freq[c]++;
}
priority_queue<Node *, vector<Node *>, compare> pq;
for (int i = 0; i < 256; i++)
{
if (freq[i] != 0)
{
pq.push(new Node(freq[i]));
}
}
while (pq.size() != 1)
{
Node *left = pq.top();
pq.pop();
Node *right = pq.top();
pq.pop();
Node *top = new Node(left->freq + right->freq);
top->left = left;
top->right = right;
pq.push(top);
}
int length = 0;
queue<pair<Node *, int>> q;
q.push({pq.top(), 0});
while (!q.empty())
{
Node *node = q.front().first;
int depth = q.front().second;
q.pop();
if (node->left == NULL && node->right == NULL)
{
length += node->freq * depth;
}
if (node->left != NULL)
{
q.push({node->left, depth + 1});
}
if (node->right != NULL)
{
q.push({node->right, depth + 1});
}
}
return length;
}
int main()
{
int t;
cin >> t;
while (t--)
{
string str;
cin >> str;
cout << howlength(str) << endl;
}
return 0;
}
parent = i;
huffTree[s2].parent = i;
huffTree[i].leftchild = s1;
huffTree[i].rightchild = s2;
huffTree[i].weight = huffTree[s1].weight + huffTree[s2].weight;
}
}
void HuffMan::Destroy()
{
len = 0;
lnum = 0;
delete[] huffTree;
delete[] huffCode;
}
void HuffMan::Coding()
{
char *cd;
int i, c, f, start;
cd = new char[lnum];
cd[lnum - 1] = '\0';
for (i = 1; i <= lnum; ++i)
{
start = lnum - 1;
for (c = i, f = huffTree[i].parent; f != 0; c = f, f = huffTree[f].parent)
{
if (huffTree[f].leftchild == c)
cd[--start] = '0';
else
cd[--start] = '1';
}
huffCode[i].assign(&cd[start]);
}
delete[] cd;
}
int HuffMan::Decode(const string codestr, char txtstr[])
{
int i, k, c;
char ch;
c = len;
k = 0;
for (i = 0; i < codestr.length(); i++)
{
ch = codestr[i];
if (ch == ‘0’)
{
c = huffTree[c].leftchild;
}
else if (ch == ‘1’)
{
c = huffTree[c].rightchild;
}
else if (ch != ‘0’ && ch != ‘1’)
{
return error;
}
if (huffTree[c].leftchild == 0 && huffTree[c].rightchild == 0)
{
txtstr[k] = huffTree[c].zhao;
k++;
c = len;
}
else
{
ch = ‘\0’;
}
}
if (ch == ‘\0’)
return error;
else
txtstr[k] = ‘\0’;
return ok;
}
int main()
{
int t, n, i, j, k;
int wt[800];
char ct[800];
HuffMan myHuff;
cin >> t;
string codestr;
char txtstr[800];
for (i = 0; i < t; i++)
{
cin >> n;
for (j = 0; j < n; j++)
{
cin >> wt[j];
}
for (j = 0; j < n; j++)
{
cin >> ct[j];
}
myHuff.MakeTree(n, wt, ct);
myHuff.Coding();
cin >> k;
for (j = 0; j < k; j++)
{
cin >> codestr;
if (myHuff.Decode(codestr, txtstr) == 1)
{
cout << txtstr << endl;
}
else
{
cout << “error” << endl;
}
}
myHuff.Destroy();
}
return 0;
}
### 赫夫曼编码长度
[Submit Page ](http://acm-sztu-edu-cn-40088-p.webvpn.sztu.edu.cn:8118/csgoj/contestexp/submit?cid=1073&pid=E) [TestData ](http://acm-sztu-edu-cn-40088-p.webvpn.sztu.edu.cn:8118/csgoj/contestexp/testdata?cid=1073&pid=E) Time Limit: 1 Sec Memory Limit: 128 Mb Submitted: 4 Solved: 3
Description
每行一个大小写英文字母组成的字符串,长度不大于 1000,通过前缀编码后最短的编码长度。
Input
每组数据一行,大小写英文字母
Output
每组数据输出赫夫曼编码长度
Sample
#### **Input**
3
AABBCCDEEEE
AAABCCC
BBACB
#### **Output**
25
11
7
```cpp
#include <iostream>
#include <queue>
#include <vector>
#include <cstring>
using namespace std;
struct Node
{
int freq;
Node *left;
Node *right;
Node(int f) : freq(f), left(NULL), right(NULL) {}
};
struct compare
{
bool operator()(Node *l, Node *r)
{
return l->freq > r->freq;
}
};
int howlength(string str)
{
int freq[256] = {0};
for (char c : str)
{
freq[c]++;
}
priority_queue<Node *, vector<Node *>, compare> pq;
for (int i = 0; i < 256; i++)
{
if (freq[i] != 0)
{
pq.push(new Node(freq[i]));
}
}
while (pq.size() != 1)
{
Node *left = pq.top();
pq.pop();
Node *right = pq.top();
pq.pop();
Node *top = new Node(left->freq + right->freq);
top->left = left;
top->right = right;
pq.push(top);
}
int length = 0;
queue<pair<Node *, int>> q;
q.push({pq.top(), 0});
while (!q.empty())
{
Node *node = q.front().first;
int depth = q.front().second;
q.pop();
if (node->left == NULL && node->right == NULL)
{
length += node->freq * depth;
}
if (node->left != NULL)
{
q.push({node->left, depth + 1});
}
if (node->right != NULL)
{
q.push({node->right, depth + 1});
}
}
return length;
}
int main()
{
int t;
cin >> t;
while (t--)
{
string str;
cin >> str;
cout << howlength(str) << endl;
}
return 0;
}