7-1 上机作业2:二叉树的建立和遍历
题目描述:
对如下二叉树
已知二叉树的完全前序序列可以唯一确定一棵二叉树。现给出二叉树的完全前序序列,使用C或C++编写算法完成:
(1) 以二叉链表为存储结构,建立二叉树;
(2) 编写先序遍历算法,输出先序遍历序列;
(3) 编写中序遍历算法,输出中序遍历序列;
(4) 编写后序遍历算法,输出后序遍历序列;
(5) 编写层序遍历算法,输出层序遍历序列,要求按层输出,每层输出一行;
(6) 编写算法,计算并输出二叉树的叶子数;
(7) 编写算法,计算并输出二叉树的高度。
输入格式:
二叉树数据元素为单个字符且各不相同,取值范围为A~Z,a~z,二叉树不为空。输入数据分为2行,第1行为二叉树完全前序序列字符(包括#)个数,第2行为二叉树的完全前序序列。例如,上面二叉树的输入为:ABD##FE###CG#H##I##,其中#代表为空的位置。
输出格式:
输出分为以下几行:
第1行为先序遍历序列
第2行为中序遍历序列
第3行为后序遍历序列
第4行及后面紧跟的几行为层序遍历序列,有几层输出几行
紧跟后面行输出叶子节点数(整数)
最后1行输出树的高度(整数)
输入样例:
以上面的二叉树为例,输入为:
19
ABD##FE###CG#H##I##
输出样例:
对于上面的输入,输出为:
preorder traversal:ABDFECGHI
inorder traversal:DBEFAGHCI
postorder traversal:DEFBHGICA
level traversal:
A
BC
DFGI
EH
4
4
其中"preorder traversal:"、"inorder traversal:"、"postorder traversal:"、"level traversal:"为先序、中序、后序序列的提示信息。
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
通过代码:
#include <bits/stdc++.h>
using namespace std;
typedef char telem;
int n,i;
char a[100];
int cnt=0;
typedef struct BTNode
{
telem data;
struct BTNode *left;
struct BTNode *right;
} Node;
Node* createBT()
{
Node *p;
telem ch;
ch=a[cnt];
if(ch=='#')
{
p=NULL;
cnt++;
}
else
{
cnt++;
p=(Node*)malloc(sizeof(Node));
p->data = ch;
p->left = createBT();
p->right = createBT();
}
return p;
}
void xianxu(Node* root)
{
if(root)
{
cout<< root->data;
xianxu(root->left);
xianxu(root->right);
}
}
void zhongxu(Node* root)
{
if(root)
{
zhongxu(root->left);
cout << root->data;
zhongxu(root->right);
}
}
void houxu(Node* root)
{
if(root)
{
houxu(root->left);
houxu(root->right);
cout << root->data;
}
}
int yezijiedianshu(Node* root)
{
if(!root)
{
return 0;
}
else if((root->left == NULL)&&(root->right == NULL))
{
return 1;
}
else
{
return yezijiedianshu(root->left)+yezijiedianshu(root->right);
}
}
int gaodu(Node* root)
{
if(root)
{
return gaodu(root->left)>gaodu(root->right)?gaodu(root->left)+1:gaodu(root->right)+1;
}
if(root == NULL)
{
return 0;
}
}
void printNodeAtLevel(Node* root,int level)
{
if(nullptr == root || level < 0 )
return;
if(0 == level)
{
std::cout << root->data;
return;
}
// 左子树的 level - 1 级
printNodeAtLevel(root->left, level - 1);
// 右子树的 level - 1 级
printNodeAtLevel(root->right, level - 1);
}
void levelOrder(Node* root)
{
if(nullptr == root)
return;
for(int i = 0; i < gaodu(root); i++)
{
printNodeAtLevel(root, i);
endl(std::cout); //打印完一层,换行
}
}
int main()
{
cin >>n;
for(i=0; i<n; i++)
{
cin >>a[i];
}
Node *root=NULL;
root = createBT();
cout <<"preorder traversal:";
xianxu(root);
cout <<endl;
cout <<"inorder traversal:";
zhongxu(root);
cout <<endl;
cout <<"postorder traversal:";
houxu(root);
cout <<endl;
cout<<"level traversal:"<<endl;
levelOrder(root);
cout <<yezijiedianshu(root)<<endl;
cout <<gaodu(root)<<endl;
return 0;
}
4-1 第4次上机作业:哈夫曼树与哈夫曼编码
4-1 哈夫曼树与哈夫曼编码
题目描述:
哈夫曼树(Huffman Tree)又称最优二叉树,是一种带权路径长度最短的二叉树。所谓树的带权路径长度,就是树中所有的叶结点的权值乘上其到根结点的路径长度(若根结点为0层,叶结点到根结点的路径长度为叶结点的层数)。树的路径长度是从树根到每一结点的路径长度之和,记为WPL=(W1L1+W2L2+W3L3+...+WnLn),N个权值Wi(i=1,2,...n)构成一棵有N个叶结点的二叉树,相应的叶结点的路径长度为Li(i=1,2,...n)。可以证明哈夫曼树的WPL是最小的。
在数据通信中,需要将传送的文字转换成二进制的字符串,用0,1码的不同排列来表示字符。例如,需传送的报文为“AFTER DATA EAR ARE ART AREA”,这里用到的字符集为“A,E,R,T,F,D”,各字母出现的次数为{8,4,5,3,1,1}。现要求为这些字母设计编码。要区别6个字母,最简单的二进制编码方式是等长编码,固定采用3位二进制,可分别用000、001、010、011、100、101对“A,E,R,T,F,D”进行编码发送,当对方接收报文时再按照三位一分进行译码。显然编码的长度取决报文中不同字符的个数。若报文中可能出现26个不同字符,则固定编码长度为5。然而,传送报文时总是希望总长度尽可能短。在实际应用中,各个字符的出现频度或使用次数是不相同的,如A、B、C的使用频率远远高于X、Y、Z,自然会想到设计编码时,让使用频率高的用短码,使用频率低的用长码,以优化整个报文编码。
为使不等长编码为前缀编码(即要求一个字符的编码不能是另一个字符编码的前缀),可用字符集中的每个字符作为叶子结点生成一棵编码二叉树,为了获得传送报文的最短长度,可将每个字符的出现频率作为字符结点的权值赋予该结点上,显然字使用频率越小权值越小,权值越小叶子就越靠下,于是频率小编码长,频率高编码短,这样就保证了此树的最小带权路径长度效果上就是传送报文的最短长度。因此,求传送报文的最短长度问题转化为求由字符集中的所有字符作为叶子结点,由字符出现频率作为其权值所产生的哈夫曼树的问题。利用哈夫曼树来设计二进制的前缀编码,既满足前缀编码的条件,又保证报文编码总长最短。
本题要求从键盘输入若干电文所用符号及其出现的频率,然后构造哈夫曼树,从而输出哈夫曼编码。
注意:
为了保证得到唯一的哈夫曼树,本题规定在构造哈夫曼树时,左孩子结点权值不大于右孩子结点权值。如权值相等,则先选优先级队列中先出队的节点作为左孩子。编码时,左分支取“0”,右分支取“1”。
输入格式:
输入有3行。
第1行:符号个数n(2~20)。
第2行:一个不含空格的字符串。记录着本题的符号表。我们约定符号都是单个的小写英文字母,且从字符‘a’开始顺序出现。也就是说,如果 n 为 2 ,则符号表为 ab ;如果 n 为 6,则符号为 abcdef;以此类推。
第3行:各符号出现频率(用乘以100后的整数),用空格分隔。
输出格式:
先输出构造的哈夫曼树带权路径长度。
接下来输出n行,每行是一个字符和该字符对应的哈夫曼编码。字符按字典顺序输出。
字符和哈夫曼编码之间以冒号分隔。
例如:
a:10
b:110
输入样例:
在这里给出一组输入。
6
abcdef
15 19 10 6 38 12
输出样例:
在这里给出相应的输出。
240
a:101
b:111
c:1101
d:1100
e:0
f:100
提示:
以上示例数据,按题目要求建立的Huffman Tree如下图:
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
通过代码:
#include<bits/stdc++.h>
using namespace std;
struct node
{
int weight;
char ch = 'z' + 1;
node *lchild;
node *rchild;
};
struct cmp
{
bool operator() (node* a, node* b)
{
if(a->weight == b->weight)
return rand()%2;
return a->weight >= b->weight;
}
};
priority_queue<node, vector<node*>, cmp> q;
vector<char> ans[30];
vector<char> code;
string str;
int n,wpl;
node* createTree()
{
node* r;
while(!q.empty())
{
if(q.size() == 1)
{
node* a = q.top();
q.pop();
r = a;
break;
}
else
{
node* a = q.top();
q.pop();
node* b = q.top();
q.pop();
node* c = new node();
c->weight = a->weight + b->weight;
c->lchild = a;
c->rchild = b;
r = c;
q.push(c);
}
}
return r;
}
void Print()
{
cout << wpl << endl;
for(int i=0; i<n; i++)
{
cout << str[i] << ":";
int index = str[i] - 'a';
for(int j=0; j<int(ans[index].size()); j++)
{
cout << ans[index][j];
}
cout << endl;
}
}
void dfs(node* root)
{
if(root->lchild != NULL || root->rchild != NULL)
{
wpl += root->weight;
}
if(root->lchild == NULL && root->rchild == NULL)
{
char ch = root->ch;
ans[ch-'a'] = code;
return;
}
if(root->lchild != NULL)
{
code.push_back('0');
dfs(root->lchild);
code.pop_back();
}
if(root->rchild != NULL)
{
code.push_back('1');
dfs(root->rchild);
code.pop_back();
}
return;
}
int main()
{
cin >> n;
cin >> str;
for(int i=0; i<n; i++)
{
node* temp = new node();
cin >> temp->weight;
temp->ch = str[i];
temp->lchild = temp->rchild = NULL;
q.push(temp);
}
node* root = createTree();
dfs(root);
Print();
return 0;
}
7-1 第5次上级作业:图的邻接矩阵存储和遍历
7-1 图的邻接矩阵存储和遍历
题目描述:
图的邻接矩阵存储用一个一维数组存储各顶点数据元素,一个二维数组存储顶点之间的邻接关系。
如上面的无向加权图,顶点数据元素为“A-Z”之间的单个字符,为了使遍历输出结果唯一,要求顶点数据元素按由小到大(ASCII码)的顺序存储。例如,对于上面的加权图,数据元素按照B、C、D、F、H、L、W、X、Y、Z的顺序存储。依附于边的权值为整数,且大于0。使用C或C++编写算法,实现:
(1)使用邻接矩阵存储结构,按照输入数据建立加权图;
(2)按存储位置,从第1个顶点出发,按照深度优先搜索算法输出各顶点数据;
(3)按存储位置,从第1个顶点出发,按照广度优先搜索算法输出各顶点数据;
(4)按存储位置,计算并输出个顶点的度。
输入格式:
输入分为以下几行,第1行为图的顶点数,第2行为图的边数,第3行及以后各行为图的各个边依附的顶点及其权值。
输出格式:
输出分为以下行,第1行为深度优先遍历序列,第2行为广度优先遍历序列,其后为各顶点及其度。
输入样例:
如上图的输入格式为:
10
17
Z B 8
Z W 5
B D 5
B W 5
B L 4
D L 4
W X 8
W H 4
L H 4
L F 2
X H 7
X Y 5
H F 3
H Y 5
H C 6
F C 7
C Y 6
输出样例:
如上图的输出为:
DFS: B D L F C H W X Y Z
BFS: B D L W Z F H X C Y
B:4
C:3
D:2
F:3
H:6
L:4
W:4
X:3
Y:3
Z:2
其中"DFS:","BFS:","B:","C:"等为提示标志,序列" B D L F C H W X Y Z"的每个字符前面有一个空格。
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
通过代码:
#include <bits/stdc++.h>
using namespace std;
vector<int>s[35];
bool st[65];
void Dfs(int u)
{
for(int i = 0;i<s[u].size();i++)
{
int j = s[u][i];
if(st[j] == 0)
{
st[j]=1;
cout << " " << char(j+'A');
Dfs(j);
}
}
}
void Bfs(int u)
{
queue<int>q;
q.push(u);
st[u]=1;
while(q.size())
{
int t = q.front();
q.pop();
for(int i = 0;i<s[t].size();i++)
{
int j = s[t][i];
if(st[j]==0)
{
st[j]=1;
cout << " " << char(j+'A');
q.push(j);
}
}
}
}
int main()
{
int n,m;
cin >> n >> m;
while(m--)
{
char a,b;
cin >> a >> b;
int w;
cin >> w;
s[a-'A'].push_back(b-'A');
s[b-'A'].push_back(a-'A');
}
int f = -1;
for(int i = 0;i<=26;i++)
{
if(s[i].size()>0&&f==-1)f = i;
sort(s[i].begin(),s[i].end());
}
cout << "DFS: " << char(f+'A');
st[f]=1;
Dfs(f);
memset(st,0,sizeof st);
cout << endl;
cout << "BFS: " << char(f+'A');
Bfs(f);
cout <<endl;
for(int i = 0;i<=26;i++)
{
if(s[i].size()>0)
{
cout << char(i+'A') << ":" << s[i].size() << endl;
}
}
return 0;
}
7-2 图的邻接表存储和遍历
题目描述:
图的邻接表存储用一个一维数组存储各顶点数据元素,用边结点构成的单链表存储元素之间的邻接关系。
如上无向加权图,图中顶点数据元素为“A-Z”之间的单个字符,为了使遍历输出结果唯一,现要求顶点数据元素按由小到大(ASCII码)的顺序存储,单链表中的边结点同样按由小到大有序排列。例如,对于上述加权图,数据元素按照A、B、C、D、E、F、G 的顺序存储,在顶点A的边链表中,第1个是(A,B)边生成的边结点,第2个是(A,D)边生成的边结点。依附于边的权值为整数,且大于0。使用C或C++编写算法,实现:
(1)以领接表为存储结构,按照输入数据建立加权图;
(2)从第1个顶点出发(A),按照深度优先搜索算法输出各顶点数据;
(3)从第1个顶点出发(A),按照广度优先搜索算法输出各顶点数据;
(4)计算并输出个顶点的度,按顶点存储顺序输出。
输入格式:
输入分为以下几行,第1行为图的顶点数,第2行为图的边数,第3行及以后为图的各个边依附的顶点及其权值。
输出格式:
输出分为以下行,第1行为深度优先遍历序列,第2行为广度优先遍历序列,其后为各顶点及其度。
输入样例:
如上图的输入格式为:
7
11
A B 7
A D 5
B C 8
B D 9
B E 7
C E 5
D E 15
D F 6
E F 8
E G 9
F G 11
输出样例:
如上图的输出为:
DFS: A B C E D F G
BFS: A B D C E F G
A:2
B:4
C:2
D:4
E:5
F:3
G:2
其中"DFS:","BFS:","B:","C:"等为提示标志,序列" A B C E D F G"的每个字符前面有一个空格。
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
通过代码:
#include <bits/stdc++.h>
using namespace std;
const int MAX_INT = 0x7fffffff;
typedef struct ENode *PENode;
struct ENode
{
char a1,a2;
int weight;
};
typedef PENode Edge;
typedef struct GNode *PGNode;
struct GNode
{
int node;
int edge;
int G[30][30];
bool N[30];
char A[30];
};
typedef PGNode GMap;
bool visit[30];
void zeroVisit(int n)
{
for(int i=0; i<n; i++)
visit[i]=0;
}
void creatMap(GMap MGraph)
{
for(int i=0; i<=25; i++)
{
MGraph->N[i]=0;
for(int j=0; j<=25; j++)
{
MGraph->G[i][j]=MAX_INT;
}
}
}
void insertEdge(GMap MGraph,Edge e)
{
int c=e->a1-'A';
int b=e->a2-'A';
MGraph->N[c]=1;
MGraph->N[b]=1;
MGraph->G[c][b]=MGraph->G[b][c]=e->weight;
}
void DFS(GMap MGraph,int node)
{
cout<<" "<<(char)(node+'A');
visit[node]=1;
for(int i=0; i<26; i++)
{
if(MGraph->G[node][i]<MAX_INT)
{
if(visit[i]==0)
{
DFS(MGraph,i);
}
}
}
}
void BFS(GMap MGraph,int node)
{
queue<int>q1;
queue<int>q2;
visit[node]=1;
q1.push(node);
while(!q1.empty()||!q2.empty())
{
while(!q1.empty())
{
int n;
n=q1.front();
cout<<" "<<(char)(n+'A');
for(int i=0; i<26; i++)
{
if(MGraph->G[n][i]<MAX_INT)
{
if(visit[i]==0)
{
q2.push(i);
visit[i]=1;
}
}
}
q1.pop();
}
while(!q2.empty())
{
int n;
n=q2.front();
cout<<" "<<(char)(n+'A');
for(int i=0; i<26; i++)
{
if(MGraph->G[n][i]<MAX_INT)
{
if(visit[i]==0)
{
q1.push(i);
visit[i]=1;
}
}
}
q2.pop();
}
}
}
void inAndout(GMap MGraph)
{
for(int i=0; i<26; i++)
{
if(MGraph->N[i]==1)
{
cout<<endl<<(char)(i+'A')<<':';
int temp=0;
for(int j=0; j<26; j++)
{
if(MGraph->G[i][j]<MAX_INT)
temp++;
}
cout<<temp;
}
}
}
int main()
{
GMap MGraph;
MGraph=(GMap)malloc(sizeof(GNode));
cin>>MGraph->node>>MGraph->edge;
creatMap(MGraph);
Edge e1;
e1=(Edge)malloc(sizeof(ENode));
for(int i=0; i<MGraph->edge; i++)
{
cin>>e1->a1>>e1->a2>>e1->weight;
insertEdge(MGraph,e1);
}
int temp=0;
for(int i=0; i<26; i++)
{
if(MGraph->N[i]==1)
{
temp=i;
break;
}
}
zeroVisit(26);
cout<<"DFS:";
DFS(MGraph,temp);
cout<<endl;
cout<<"BFS:";
zeroVisit(26);
BFS(MGraph,temp);
inAndout(MGraph);
return 0;
}
7-1 第六次上级作业 查找上机作业:二叉排序树和平衡二叉树
7-1 查找上机作业:二叉排序树和平衡二叉树
题目描述:
二叉排序树(BST树)的任何结点均满足:“若左子树存在,根结点大于其左子树上的所有结点;若右子树存,根结点小于其右子树上的所有结点。给定一个数据序列(所有数据互不相等),可以构造二叉排序树。例如:按照下面的数据序列及其先后顺序{ 10,30,20,7,5,6,2,9,28 }可构造出如下的二叉排序树。
平衡二叉树(AVL树)是一种二叉排序树,同时要求每个结点左右子树的高度最多相差为1。对上述数据序列,同样按照数据序列及其先后顺序构造平衡二叉树,可构造出如下的平衡二叉树。
对序列中的数据元素进行查找,对于单个数据而言,平衡二叉树查找成功的比较次数不一定比二叉排序树小,但是,在每个数据元素查找的等概率下,平衡二叉树查找成功的平均查找长度要小于二叉排序树的平均查找长度。使用C或C++编写算法完成:
(1)按给定数据序列及其顺序构建二叉排序树;
(2)按给定数据序列及其顺序构建平衡二叉树;
(3)计算并输出二叉排序树中所有数据元素在查找等概率下的平均查找长度;
(4)计算并输出平衡二叉树中所有数据元素在查找等概率下的平均查找长度。
输入格式:
输入分为2行,第1行为数据元素个数,第2行为数据元素,其中个数据元素为整数。
输出格式:
输出分为2行,第1行为二叉排序树的平均查找长度,第2行为平衡二叉树的平均查找长度。平均查找长度位置输出所有数据元素查找成功的比较次数之和即可。这样输出就是一个整数了。
输入样例:
对于上面的数据序列,输入格式为:
9
10,30,20,7,5,6,2,9,28
输出样例:
对于上面的数据序列,输出格式为:
BST-ASL:26
AVL-ASL:25
其中“BST-ASL:”和“AVL-ASL:”为二叉排序树和平衡二叉树的平均查找长度提示,其后为各自树中所有数据查找成功的比较次数之和。
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
通过代码:
#include <iostream>
using namespace std;
typedef struct TreeNode
{
int num;
int deep;
int bf;
TreeNode *left;
TreeNode *right;
} * Tree;
Tree bulid_bst(Tree p, Tree t)
{
Tree n;
n = t;
int i = 1;
if (t->num == -1)
{
t->num = p->num;
t->deep = i;
}
else
{
while (true)
{
i++;
if (p->num < n->num)
{
if (n->left == NULL)
{
p->deep = i;
n->left = p;
break;
}
else
{
n = n->left;
}
}
else
{
if (n->right == NULL)
{
p->deep = i;
n->right = p;
break;
}
else
{
n = n->right;
}
}
}
}
return t;
}
int getdeep(TreeNode *t)
{
if (t == NULL)
return -1;
else
return t->deep;
}
bool isBalanced(TreeNode *left, TreeNode *right)
{
return abs(getdeep(left) - getdeep(right)) < 2;
}
//左左
TreeNode *SingleRotateLeft(TreeNode *t2)
{
TreeNode *t1;
t1 = t2->left;
t2->left = t1->right;
t1->right = t2;
t2->deep = max(getdeep(t2->left), getdeep(t2->right)) + 1;
t1->deep = max(getdeep(t1->left), getdeep(t1->right)) + 1;
return t1;
}
//右右
TreeNode* SingleRotateRight(TreeNode* t2)
{
TreeNode *t1;
t1 = t2->right;
t2->right = t1->left;
t1->left = t2;
t2->deep = max(getdeep(t2->left), getdeep(t2->right)) + 1;
t1->deep = max(getdeep(t1->left), getdeep(t1->right)) + 1;
return t1;
}
//左右
TreeNode *DoubleRotateLR(TreeNode *t3)
{
t3->left = SingleRotateRight(t3->left);
return SingleRotateLeft(t3);
}
//右左
TreeNode *DoubleRotateRL(TreeNode *t3)
{
t3->right = SingleRotateLeft(t3->right);
return SingleRotateRight(t3);
}
TreeNode *insert(int v, TreeNode *root)
{
if (root == NULL)
{
root = (Tree)malloc(sizeof(TreeNode));
root->num = v;
root->left = NULL;
root->right = NULL;
root->deep = 0;
return root;
}
if (v > root->num) //节点插入在右子树中
{
root->right = insert(v, root->right);
if (!isBalanced(root->left, root->right))
{
if (v > root->right->num)
root = SingleRotateRight(root);
else
root = DoubleRotateRL(root);
}
}
else
{
root->left = insert(v, root->left);
if (!isBalanced(root->left, root->right))
{
if (v < root->left->num)
root = SingleRotateLeft(root);
else
root = DoubleRotateLR(root);
}
}
root->deep = max(getdeep(root->left), getdeep(root->right)) + 1;
return root;
}
int bst_avl(Tree t)
{
if (t->left == NULL && t->right == NULL)
{
return t->deep;
}
else
{
if (t->left == NULL)
{
return bst_avl(t->right) + t->deep;
}
if (t->right == NULL)
{
return bst_avl(t->left) + t->deep;
}
}
return t->deep + bst_avl(t->left) + bst_avl(t->right);
}
void fun(Tree t)
{
if(t->left != NULL)
{
t->left->deep = t->deep +1;
fun(t->left);
}
if(t->right != NULL)
{
t->right->deep = t->deep +1;
fun(t->right);
}
}
int main()
{
int n;
char s;
Tree t;
Tree root;
root = NULL;
t = (Tree)malloc(sizeof(TreeNode));
t->num = -1;
t->left = NULL;
t->right = NULL;
cin >> n;
int a[n + 5];
for (int i = 0; i < n; i++)
{
Tree p, q;
p = (Tree)malloc(sizeof(TreeNode));
p->left = NULL;
p->right = NULL;
q = (Tree)malloc(sizeof(TreeNode));
q->left = NULL;
q->right = NULL;
q->bf = 0;
if (i != 0)
{
cin >> s;
}
cin >> p->num;
t = bulid_bst(p, t);
root = insert(p->num,root);
}
cout << "BST-ASL:" <<bst_avl(t) << endl;
root->deep = 1;
fun(root);
cout << "AVL-ASL:"<<bst_avl(root);
return 0;
}
写在最后
以上代码仅供同学们参考,切勿复制粘贴、1草草了事,东西是给自己学的、对自己负责;时间关系没有给大家做代码注释,希望同学们上课时候认真听讲、做到举一反三。
如有雷同纯属巧合、若有侵权请及时联系删文