树
树(tree)是包含n(n>=0)个结点的有穷集,其中:
(1)每个元素称为节点(node);
(2)有一个特定的节点被称为根节点或树根(root)。
(3)除根结点之外的其余数据元素被分为m(m≥0)个互不相交的集合T1,T2,……Tm-1,其中每一个集合Ti(1<=i<=m)本身也是一棵树,被称作原树的子树(subtree)。
二叉树
二叉树是每个节点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。二叉树常被用于实现二叉查找树和二叉堆。
二叉树的构造输出
#include<iostream>
using namespace std;
struct TreeNode
{
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int val) :val(val), left(NULL), right(NULL)
{
}
};
void coutTreeNode(TreeNode *root, int layer)
{
if(!root)
{
return;
}
for (int i = 0; i < layer; i++)
{
cout << " ";
}
cout << root->val << endl;
coutTreeNode(root->left, layer + 1);
coutTreeNode(root->right, layer + 1);
}
int main()
{
TreeNode a(10);
TreeNode b(9);
TreeNode c(8);
TreeNode d(7);
TreeNode e(6);
TreeNode f(5);
a.left = &b;
a.right = &c;
b.left = &d;
b.right = &e;
c.left = &f;
coutTreeNode(&a, 0);
return 0;
}
二叉树的深度遍历
三种遍历方式:
- 前序遍历:“中左右”,下图前序遍历为---12435786
- 中序遍历:“左中右”,下图中序遍历为---42175836
- 后序遍历:“左右中”,下图后序遍历为---42785631
前序遍历
void coutTreeNode(TreeNode *root, int layer)
{
if(!root)
{
return;
}
for (int i = 0; i < layer; i++)
{
cout << " ";
}
cout << root->val << endl;
coutTreeNode(root->left, layer + 1);
coutTreeNode(root->right, layer + 1);
}
中序遍历
void coutTreeNode(TreeNode *root, int layer)
{
if(!root)
{
return;
}
coutTreeNode(root->left, layer + 1);
for (int i = 0; i < layer; i++)
{
cout << " ";
}
cout << root->val << endl;
coutTreeNode(root->right, layer + 1);
}
后序遍历
void coutTreeNode(TreeNode *root, int layer)
{
if(!root)
{
return;
}
coutTreeNode(root->left, layer + 1);
coutTreeNode(root->right, layer + 1);
for (int i = 0; i < layer; i++)
{
cout << " ";
}
cout << root->val << endl;
}
二叉树按层遍历求路径之和
给定一个二叉树与sum,sum为33,找出所有从根节点到叶子节点的路径,这些路径上的节点值累加和为sum。
#include<iostream>
#include<vector>
using namespace std;
struct TreeNode
{
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int val) :val(val), left(NULL), right(NULL)
{
}
};
void pathValueSummation(TreeNode *root, int &value, int sum, std::vector<int> &path, std::vector<std::vector<int>> &result)
{
if (!root)
{
return;
}
value += root->val;//先序遍历累加节点值
path.push_back(root->val);
if (!root->left && !root->right && value == sum)
{
result.push_back(path);
}
pathValueSummation(root->left, value, sum, path, result);
pathValueSummation(root->right, value, sum, path, result);
value -= root->val;//后序遍历减去节点值,返回上节点
path.pop_back();
}
std::vector<std::vector<int>> TreeNodeSum(TreeNode *root, int sum)
{
std::vector<std::vector<int>> result;//存储累加结果符合条件的
std::vector<int> path; //存储路径的对应值
int value = 0;
pathValueSummation(root, value, sum, path, result);
return result;
}
int main()
{
TreeNode a(10);
TreeNode b(8);
TreeNode c(6);
TreeNode d(15);
TreeNode e(7);
TreeNode f(9);
TreeNode g(3);
TreeNode h(8);
a.left = &b;
a.right = &c;
b.left = &d;
b.right = &e;
c.left = &f;
e.left = &g;
e.right = &h;
std::vector<std::vector<int>> result = TreeNodeSum(&a, 33);
for (int i = 0; i < result.size(); i++)
{
for (int j = 0; j < result[i].size(); j++)
{
cout << result[i][j] << " ";
}
cout << endl;
}
return 0;
}
二叉树转链表
给定一个二叉树,要求将其转换成一个单链表,单链表的节点顺序为先序遍历。
容器实现方式
#include<iostream>
#include<vector>
using namespace std;
struct TreeNode
{
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int val) :val(val), left(NULL), right(NULL)
{
}
};
void saveInVector(TreeNode* root, std::vector<TreeNode*> &treeNodeVec)
{
if (!root)
{
return;
}
treeNodeVec.push_back(root);//先序遍历节点,按该顺序填入vector
saveInVector(root->left, treeNodeVec);
saveInVector(root->right, treeNodeVec);
}
void transformList(TreeNode * root)
{
std::vector<TreeNode *> treeNodeVec;
saveInVector(root, treeNodeVec);
for (int i = 0; i < treeNodeVec.size()-1; i++)
{
treeNodeVec[i]->left = nullptr;
treeNodeVec[i]->right = treeNodeVec[i + 1];
}
}
int main()
{
TreeNode a(10);
TreeNode b(8);
TreeNode c(6);
TreeNode d(15);
TreeNode e(7);
TreeNode f(9);
TreeNode g(3);
TreeNode h(8);
a.left = &b;
a.right = &c;
b.left = &d;
b.right = &e;
c.left = &f;
e.left = &g;
e.right = &h;
TreeNode* root = &a;
transformList(root);
while (root)
{
cout << root->val << " ";
root = root->right;
}
return 0;
}
遍历实现
#include<iostream>
#include<vector>
using namespace std;
struct TreeNode
{
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int val) :val(val), left(NULL), right(NULL)
{
}
};
void transformToList(TreeNode * root, TreeNode* &last)
{
if (!root)
{
return;
}
if (!root->left && !root->right)
{
last = root;
return;
}
TreeNode *left = root->left;//备份一下 左右子树的节点
TreeNode *right = root->right;
TreeNode *left_last = nullptr;//代表左右子树的最后一个节点
TreeNode *right_last = nullptr;
if (left)
{
transformToList(left, left_last);
root->right = left;
root->left = nullptr;
last = left_last;
}
if (right)
{
transformToList(right, right_last);
if (left_last)
{
left_last->right = right;
}
last = right_last;
}
}
void flattenOperate(TreeNode* root)
{
TreeNode *last = nullptr;
transformToList(root, last);
}
int main()
{
TreeNode a(10);
TreeNode b(8);
TreeNode c(6);
TreeNode d(15);
TreeNode e(7);
TreeNode f(9);
TreeNode g(3);
TreeNode h(8);
a.left = &b;
a.right = &c;
b.left = &d;
b.right = &e;
c.left = &f;
e.left = &g;
e.right = &h;
TreeNode* root = &a;
flattenOperate(root);
while (root)
{
cout << root->val << " ";
root = root->right;
}
return 0;
}
求二叉树两个根节点的最近的祖先
已知存在一个二叉树,给定两个节点,求该两节点的最近公共祖先
#include<iostream>
#include<vector>
using namespace std;
struct TreeNode
{
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int val) :val(val), left(NULL), right(NULL)
{
}
};
//正在遍历的节点 要搜索查找的节点 遍历时存储的节点路径 存储搜索到对应节点后的路径结果 记录查找状态(找到为1,否则为0)
void pathOfTreeNode(TreeNode * root, TreeNode* search,std::vector<TreeNode*> &path,std::vector<TreeNode*> &result,int &finish)
{
if (!root || finish)
{
return;
}
path.push_back(root);//先序遍历,存储遍历的节点路径
if (root == search)
{
finish = 1;
result = path;
}
pathOfTreeNode(root->left, search, path, result, finish);//深度遍历root左孩子
pathOfTreeNode(root->right, search, path, result, finish);//深度遍历root右孩子
path.pop_back();//当遍历一个节点的左子树和后子树后未找到对应节点则将该节点移除出vector
}
TreeNode* latelyCommonTreeNode(TreeNode* root, TreeNode * p, TreeNode *q)
{
std::vector<TreeNode*> path;//声明遍历用的存储路径的栈
std::vector<TreeNode*> p_node_path;//存储p节点的路径
std::vector<TreeNode*> q_node_path;//存储q节点的路径
int finish = 0;//记录搜索状态finish
pathOfTreeNode(root, p, path, p_node_path, finish);
path.clear();
finish = 0;
pathOfTreeNode(root, q, path, q_node_path, finish);
int lengthOfpath = 0;//较短路径的长度
if (p_node_path.size() < q_node_path.size())
{
lengthOfpath = p_node_path.size();
}
else
{
lengthOfpath = q_node_path.size();
}
TreeNode* result = 0;
for (int i = 0; i < lengthOfpath; i++)//同时遍历根到pq节点的路径上的节点
{
if (p_node_path[i] == q_node_path[i])
{
result = p_node_path[i];//找到最近的公共祖先
}
}
return result;
}
int main()
{
TreeNode a(10);
TreeNode b(8);
TreeNode c(6);
TreeNode d(15);
TreeNode e(7);
TreeNode f(9);
TreeNode g(3);
TreeNode h(8);
a.left = &b;
a.right = &c;
b.left = &d;
b.right = &e;
c.left = &f;
e.left = &g;
e.right = &h;
TreeNode* root = &a;
TreeNode* result = nullptr;
result = latelyCommonTreeNode(root,&d,&h);
cout <<"d和h的最近共同祖先为:"<< result->val << " " << endl;//8
result = latelyCommonTreeNode(root, &e, &f);
cout << "e和f的最近共同祖先为:" << result->val << " " << endl;//10
return 0;
}
二叉树的宽度优先搜素
二叉树的宽度优先搜索,又称为二叉树的层次遍历,桉树的层次依次访问树的节点。层次遍历使用队列对遍历节点进行存储,先进入队列的节点,优先遍历拓展其左右孩子。
#include<iostream>
#include<queue>
using namespace std;
struct TreeNode
{
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int val) :val(val), left(NULL), right(NULL)
{
}
};
void breadthFirst(TreeNode * root)//宽度优先搜素
{
std::queue<TreeNode*> treeNodeQueue;
treeNodeQueue.push(root);
while (!treeNodeQueue.empty())
{
TreeNode *node = treeNodeQueue.front();
treeNodeQueue.pop();
cout << node->val << " ";
if (node->left)
{
treeNodeQueue.push(node->left);
}
if (node->right)
{
treeNodeQueue.push(node->right);
}
}
}
int main()
{
TreeNode a(10);
TreeNode b(8);
TreeNode c(6);
TreeNode d(15);
TreeNode e(7);
TreeNode f(9);
TreeNode g(3);
TreeNode h(8);
a.left = &b;
a.right = &c;
b.left = &d;
b.right = &e;
c.left = &f;
e.left = &g;
e.right = &h;
TreeNode* root = &a;
breadthFirst(root);
return 0;
}
二叉树的的侧面观察
已知存在一个二叉树,顺序输出从右侧观察到的二叉树节点。
#include<iostream>
#include<queue>
#include<vector>
using namespace std;
struct TreeNode
{
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int val) :val(val), left(NULL), right(NULL)
{
}
};
std::vector<int> rightSideOfBF(TreeNode * root)//宽度优先搜素 右侧观察到节点顺序
{
std::vector<int> viewVec;//存储按层次遍历的最后一个节点
std::queue<std::pair<TreeNode*, int>> treeNodeQueue;//宽度优先搜索队列 将节点与层数绑定为pair 存储<节点,层数>
if (root)
{
treeNodeQueue.push(std::make_pair(root, 0));
}
while (!treeNodeQueue.empty())
{
TreeNode* node = treeNodeQueue.front().first;//搜索节点
int depth = treeNodeQueue.front().second;//搜索节点所在的层数
treeNodeQueue.pop();
if (viewVec.size() == depth)
{
viewVec.push_back(node->val);
}
else
{
viewVec[depth] = node->val;
}
if (node->left)
{
treeNodeQueue.push(std::make_pair(node->left, depth + 1));
}
if (node->right)
{
treeNodeQueue.push(std::make_pair(node->right, depth + 1));
}
}
return viewVec;
}
int main()
{
TreeNode a(10);
TreeNode b(8);
TreeNode c(6);
TreeNode d(15);
TreeNode e(7);
TreeNode f(9);
TreeNode g(3);
TreeNode h(8);
a.left = &b;
a.right = &c;
b.left = &d;
b.right = &e;
c.left = &f;
e.left = &g;
e.right = &h;
TreeNode* root = &a;
std::vector<int> result = rightSideOfBF(root);
for (int i = 0; i < result.size(); i++)
{
cout << result[i] << " ";
}
return 0;
}
图
图是由定点的有穷非空集合和顶点之间边的集合组成,通常表示为G(V,E),其中,G表示一个图,V是图G中定点的集合,E是图G中边的集合。图分有向图与无向图,根据图的边长,又分为带权图和不带权图。
图的构造表示
#include<iostream>
#include<vector>
using namespace std;
struct GraphNode
{
int val;
std::vector<GraphNode*> neighbors;
GraphNode(int val) :val(val)
{
}
};
int main()
{
int const MAX_NUM = 6;
GraphNode* graph[MAX_NUM];
for (int i = 0; i < MAX_NUM; i++)//构造图的节点
{
graph[i] = new GraphNode(i);
}
graph[0]->neighbors.push_back(graph[2]);
graph[0]->neighbors.push_back(graph[3]);
graph[1]->neighbors.push_back(graph[0]);
graph[1]->neighbors.push_back(graph[2]);
graph[2]->neighbors.push_back(graph[3]);
graph[3]->neighbors.push_back(graph[2]);
graph[3]->neighbors.push_back(graph[4]);
graph[5]->neighbors.push_back(graph[4]);
graph[5]->neighbors.push_back(graph[0]);
cout << "该图表示为:" << endl;
for (int i = 0; i < MAX_NUM; i++)
{
cout << "当前节点为:" << i << " ";
cout << "其子节点为:";
for (int j = 0; j < graph[i]->neighbors.size(); j++)
{
cout << graph[i]->neighbors[j]->val << " ";
}
cout << endl;
}
for (int i = 0; i < MAX_NUM; i++)
{
delete graph[i];
}
return 0;
}
图的深度优先遍历
从图中某个顶点v出发,首先访问该顶点,然后依次从它的各个未被访问的邻接点出发深度优先搜索遍历图,直至图中所有和v有路径相通且未被访问的顶点都被访问到。若此时还有其他顶点未被访问到,则另选一个未被访问的顶点坐起始点,重复上述操作,直至图中所有顶点都被访问到为止。
#include<iostream>
#include<vector>
using namespace std;
struct GraphNode
{
int val;
std::vector<GraphNode*> neighbors;
GraphNode(int val) :val(val)
{
}
};
void depthFirstSearch(GraphNode* node, int visited[])
{
visited[node->val] = 1;
cout << node->val;
for (int i = 0; i < node->neighbors.size(); i++)
{
if (visited[node->neighbors[i]->val] == 0)
{
depthFirstSearch(node->neighbors[i], visited);
}
}
}
int main()
{
int const MAX_NUM = 6;
GraphNode* graph[MAX_NUM];
for (int i = 0; i < MAX_NUM; i++)//构造图的节点
{
graph[i] = new GraphNode(i);
}
graph[0]->neighbors.push_back(graph[2]);
graph[0]->neighbors.push_back(graph[3]);
graph[1]->neighbors.push_back(graph[0]);
graph[1]->neighbors.push_back(graph[2]);
graph[2]->neighbors.push_back(graph[3]);
graph[3]->neighbors.push_back(graph[2]);
graph[3]->neighbors.push_back(graph[4]);
graph[5]->neighbors.push_back(graph[4]);
graph[5]->neighbors.push_back(graph[0]);
int visited[MAX_NUM] = { 0 };
for (int i = 0; i < MAX_NUM; i++)
{
if (visited[i] == 0)
{
cout << "当前顶点值:" << graph[i]->val<<"深度遍历顺序: ";
depthFirstSearch(graph[i], visited);
cout << endl;
}
}
for (int i = 0; i < MAX_NUM; i++)
{
delete graph[i];
}
return 0;
}
/*
当前顶点值:0深度遍历顺序: 0234
当前顶点值:1深度遍历顺序: 1
当前顶点值:5深度遍历顺序: 5
*/
图的宽度优先遍历
给定一个图,从图的某个顶点出发,在访问了v之后依次访问v的各个未曾访问过的邻接点,然后分别从这些邻接点出发依次访问它们的邻接点,并使得“先被访问的顶点的邻接点先于后被访问的顶点的邻接点的被访问”,直至图中所有已被访问的顶点的邻接点都被访问到。如果此时图中还有顶点未被访问到,则需要另选一个未曾访问过的顶点作为新的起始点,重复上述操作,直至图中所有的顶点都被访问到为止。
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
struct GraphNode
{
int val;
std::vector<GraphNode*> neighbors;
GraphNode(int val) :val(val)
{
}
};
void widthFirstSearch(GraphNode* node, int visited[])
{
std::queue<GraphNode*> graphNodeQueue;
graphNodeQueue.push(node);
visited[node->val] = 1;
while (!graphNodeQueue.empty())
{
GraphNode * firstNode = graphNodeQueue.front();
graphNodeQueue.pop();
cout << firstNode->val;
for (int i = 0; i < firstNode->neighbors.size(); i++)
{
if (visited[firstNode->neighbors[i]->val]==0)
{
graphNodeQueue.push(firstNode->neighbors[i]);
visited[firstNode->neighbors[i]->val] = 1;
}
}
}
}
int main()
{
int const MAX_NUM = 6;
GraphNode* graph[MAX_NUM];
for (int i = 0; i < MAX_NUM; i++)//构造图的节点
{
graph[i] = new GraphNode(i);
}
graph[0]->neighbors.push_back(graph[2]);
graph[0]->neighbors.push_back(graph[3]);
graph[1]->neighbors.push_back(graph[0]);
graph[1]->neighbors.push_back(graph[2]);
graph[2]->neighbors.push_back(graph[3]);
graph[3]->neighbors.push_back(graph[2]);
graph[3]->neighbors.push_back(graph[4]);
graph[5]->neighbors.push_back(graph[4]);
graph[5]->neighbors.push_back(graph[0]);
int visited[MAX_NUM] = { 0 };
for (int i = 0; i < MAX_NUM; i++)
{
if (visited[i] == 0)
{
cout << "当前顶点值:" << graph[i]->val<<"宽度遍历顺序: ";
widthFirstSearch(graph[i], visited);
cout << endl;
}
}
for (int i = 0; i < MAX_NUM; i++)
{
delete graph[i];
}
return 0;
}
/*
当前顶点值:0宽度遍历顺序: 0234
当前顶点值:1宽度遍历顺序: 1
当前顶点值:5宽度遍历顺序: 5
*/
判定图是否存在环
已知存在n个课程,它们之间存在m个依赖关系,可以理解成顶点个数为n,边个数为m的有向图,若有向图无环,则可以完成全部课程,否则不能。试问该构成的图是否存在环?
图的深度搜索实现
在深度搜索时,如果正在搜索的某一顶点(还未退出该顶点的递归深度搜索),又回到了该顶点,即证明图有环。
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
struct GraphNode
{
int val;
std::vector<GraphNode*> neighbors;
GraphNode(int val) :val(val)
{
}
};
bool depthFirstSearch(GraphNode* node, std::vector<int> &visited)
{
visited[node->val] = 0;
for (int i = 0; i < node->neighbors.size(); i++)
{
if (visited[node->neighbors[i]->val] == -1)
{
if (depthFirstSearch(node->neighbors[i], visited) == 0)
{
return false;
}
}
else if (visited[node->neighbors[i]->val] == 0)
{
return false;
}
}
visited[node->val] = 1;
return true;
}
//pair<课程1,课程2> 课程1依赖课程2即课程2指向课程1
bool ifCanFinish(int coursesNum, std::vector<std::pair<int, int>> &relationVec)
{
std::vector<GraphNode*> graphNodeVec;
std::vector<int> visited;//节点访问状态,-1表示未访问过,0代表正在访问,1表示已完成访问
for (int i = 0; i < coursesNum; i++)
{
graphNodeVec.push_back(new GraphNode(i));
visited.push_back(-1);
}
for (int i = 0; i < relationVec.size(); i++)
{
GraphNode *begin = graphNodeVec[relationVec[i].second];
GraphNode *end = graphNodeVec[relationVec[i].first];
begin->neighbors.push_back(end);
}
for (int i = 0; i < graphNodeVec.size(); i++)
{
if (visited[i] == -1 && !depthFirstSearch(graphNodeVec[i], visited))
{
return false;
}
}
for (int i = 0; i < coursesNum; i++)
{
delete graphNodeVec[i];
}
return true;
}
int main()
{
std::vector<std::pair<int, int>> relationVec;
relationVec.push_back(std::make_pair(0, 1));//图有环
relationVec.push_back(std::make_pair(2, 1));
relationVec.push_back(std::make_pair(2, 0));
relationVec.push_back(std::make_pair(3, 2));
relationVec.push_back(std::make_pair(0, 3));
bool result = ifCanFinish(4, relationVec);
cout << result << endl;//0
relationVec.clear();
relationVec.push_back(std::make_pair(0, 1));//图无环
relationVec.push_back(std::make_pair(2, 1));
relationVec.push_back(std::make_pair(2, 0));
relationVec.push_back(std::make_pair(2, 3));
relationVec.push_back(std::make_pair(0, 3));
result = ifCanFinish(4, relationVec);
cout << result << endl;//1
return 0;
}
图的宽度优先搜索
宽度优先搜索,直将入度为0的点添加至队列。当完成一个顶点的搜索(从队列中取出),它指向的所有顶点入度都减1,若此时某顶点入度为0则添加至队列,若完成宽度搜索后,所有的顶点入度都为0,则图无环,否则有环。
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
struct GraphNode
{
int val;
std::vector<GraphNode*> neighbors;
GraphNode(int val) :val(val)
{
}
};
//pair<课程1,课程2> 课程1依赖课程2即课程2指向课程1
bool ifCanFinish(int coursesNum, std::vector<std::pair<int, int>> &relationVec)
{
std::vector<GraphNode*> graphNodeVec;
std::vector<int> degree;//记录顶点的度
for (int i = 0; i < coursesNum; i++)
{
degree.push_back(0);
graphNodeVec.push_back(new GraphNode(i));
}
for (int i = 0; i < relationVec.size(); i++)
{
GraphNode* begin = graphNodeVec[relationVec[i].second];
GraphNode* end = graphNodeVec[relationVec[i].first];
begin->neighbors.push_back(end);
degree[relationVec[i].first]++;
}
std::queue<GraphNode*> graphNodeQueue;
for (int i = 0; i < coursesNum; i++)
{
if (degree[i] == 0)
{
graphNodeQueue.push(graphNodeVec[i]);
}
}
while (!graphNodeQueue.empty())
{
GraphNode* node = graphNodeQueue.front();
graphNodeQueue.pop();
for (int i = 0; i < node->neighbors.size(); i++)
{
degree[node->neighbors[i]->val]--;
if (degree[node->neighbors[i]->val] == 0)
{
graphNodeQueue.push(node->neighbors[i]);
}
}
}
for (int i = 0; i < graphNodeVec.size(); i++)
{
delete graphNodeVec[i];
}
for (int i = 0; i < degree.size(); i++)
{
if (degree[i])
{
return false;
}
}
return true;
}
int main()
{
std::vector<std::pair<int, int>> relationVec;
relationVec.push_back(std::make_pair(0, 1));//图有环
relationVec.push_back(std::make_pair(2, 1));
relationVec.push_back(std::make_pair(2, 0));
relationVec.push_back(std::make_pair(3, 2));
relationVec.push_back(std::make_pair(0, 3));
bool result = ifCanFinish(4, relationVec);
cout << result << endl;//0
relationVec.clear();
relationVec.push_back(std::make_pair(0, 1));//图无环
relationVec.push_back(std::make_pair(2, 1));
relationVec.push_back(std::make_pair(2, 0));
relationVec.push_back(std::make_pair(2, 3));
relationVec.push_back(std::make_pair(0, 3));
result = ifCanFinish(4, relationVec);
cout << result << endl;//1
return 0;
}