数据的基本单位是数据元素,在涉及到数据处理时数据元素之间的关系称之为结构,咱们依据数据元素之间关系的不一样,将数据结构分为线性结构和非线性结构 两种。html
这上面所划分的是数据结构的逻辑结构,而数据是如何在计算机中存储的,这涉及到数据的物理结构,逻辑结构是从解决问题出发,涉及到功能的简历,物理结构设计到响应速度,处理、修改、存储时间等问题。node
二叉树遍历是最基本的操做,分为先序遍历,中序遍历、后序遍历,以及层次遍历。ios
void pre_order(BTree *root){ if (root != NULL){ visit(root); //cout<<root->value pre_order(root->leftchild); pre_order(root->rightchild); } }
void in_order(BTree* root){ if (root != NULL){ in_order(root->leftchild); visit(root); in_order(root->rightchild); } }
void post_order(BTree * root){ if (root != NULL){ post_order(root->leftchild); post_order(root->rightchild); visit(root); } }
#include<iostream> #include<string> #include<stack> using namesapce std; typedef struct node{ int data; struct node *leftchild, *rightchild; }BTree; void pre_order(BTree *root){ stack<BTree*> s; BTree *p = root; //当栈非空或者p指针非空时执行 while (p != NULL || !s.empty()){ while (p != NULL){ cout << p->data; s.push(p); p = p->leftchild; } if (!s.empty()){ p = s.top(); s.pop(); p->p->rightchild; } } }
void in_order(BTree * root){ stack<BTree *> s; BTree * p = root; while (p != NULL || !s.empty()){ while (P != NULL){ s.push(p); p = p->leftchild; } if (!s.empty()){ p = s.top; cout << p->data; s.pop(); p = p->rightchild; } } }
void post_order(BTree *root){ stack<BTree *> s; BTree *p = root, *r = NULL; while (p != NULL || !s.empty()){ if (p != NULL){ s.push(p); p = p->leftchild; // 最左边 } else{ p = s.top(); //右子树存在且没有被访问过 if (p->rightchild != NULL && p->rightchild != r){ p = p->rightchild; s.push(p); p = p->leftchild; } else{ p = s.top(); //弹出结点并访问 s.pop(); cout << p->data; r = p; p = NULL; } } } }
方法二:
对于任一结点,线将其入栈,若是结点P不存在左孩子和右孩子,则能够直接访问它,若是P上存在左孩子或者右孩子,可是左孩子或者右孩子已经访问过了,则直接访问该结点,不然,将P的右孩子和左孩子依次入栈。
这种方法要简单一些。算法
void post_order(BTree *root){ stack<BTree *> s; BTree *cur = NULL; //当前结点 BTree *pre = NULL; //前一次访问的结点 s.push(root); while (!s.empty()){ cur = s.top(); if ((cur->leftchild == NULL && cur->rightchild == NULL) || (pre != NULL && (pre == cur->leftchild || pre == cur->rightchild))){ //若是当前结点没有孩子结点或者孩子结点已经被访问过 cout << cur->data; s.pop(); pre = cur; } else{ if (cur->rightchild != NULL) s.push(cur->rightchild); if (cur ->rightchild != NULL) s.push(cur->leftchild); } } }
// 输出以root为根结点的第level层中的全部结点(从左向右) // 成功返回 1 // 递归实现 int printNodeAtLevel(BinaryNode *root, int level){ if (!root || level < 0) return 0; if (level == 0){ // 根结点为0深度 cout << root->data << " "; return 1; } return printNodeAtLevel(root->leftchild,level -1) + printNodeAtLevel(root->rightchild,level-1); }
void layer_order(BTree *tree){ if (tree == NULL) return; queue<BTree *> q; q.push(tree); BTree * p = NULL; while (!q.empty()){ p = que.front(); visit(p); que.pop(); if (p->leftchild != NULL) que.push(p->leftchild); if (p->rightchild != NULL) que.push(p->rightchild); } } // 本身实现队列 # define max 1000; typedef struct sequeue{ BTree data[max]; int front; int rear; }sequeue; void enter(sequeue *q, BTree t){ if (q->rear == max){ cout << "the queue is full" << endl; } else{ q->data[q->rear] = t; q->rear++; } } BTree del(sequeue *q, BTree t){ if (q->front == q->rear){ return NULL; } else{ q->frot++; return q->data[q->front -1] } } void level_tree(bintree t){ sequeue q; Btree temp; q.front = q.rear = 0; if (!t){ printf("the tree is empty\n"); return; } enter(&q, t); while (q.front != q.rear){ t = del(&q); printf("%c ", t->data); if (t->lchild){ enter(&q, t->lchild); } if (t->rchild){ enter(&q, t->rchild); } } }
比较两棵二叉树是否相等,注意是否能够旋转的问题数组
bool isequal(BinaryNode *root1, BinaryNode *root2){ if (root1 == NULL && root2 == NULL) return true; if (!root1 || !root2) return false; if (root1->data == root2->data) return isequal(root1->leftchild, root2->leftchild) && isequal(root1->rightchild, root2->rightchild); else return false; } //若是左右节点能够旋转 return (isequal(root1->leftchild, root2->leftchild) && isequal(root1->rightchild, root2->rightchild)) || isequal(root1->leftchild, root2->rightchild) && isequal(root1->rightchild, root2->leftchild);
本质上是二叉树的遍历,先求出左右子树的深度,才能求出根结点的深度网络
int tree_height(BinaryNode *root){ int left, right; if (root == NULL) return -1; left = tree_height(root->leftchild); right = tree_height(root->rightchild); return (left > right) ? left : right; }
《编程之美: 求二叉树中节点的最大距离》的另外一个解法数据结构
所以状况A须要子树的最大深度,B须要子树的最大距离。函数
struct result{ int nMaxDistance; // 最大距离 int nMaxDepth; // 最大深度 }; result getMaximumDistance(BinaryNode *root){ if (!root){ result empty = { 0, -1 }; //最大深度初始化为 -1,调用者要对它加1,而后变为0 return empty; } result res; result lhs = getMaximumDistance(root->leftchild); result rhs = getMaximumDistance(root->rightchild); res.nMaxDepth = max(lhs.nMaxDepth + 1, rhs.nMaxDepth + 1); res.nMaxDistance = max(max(lhs.nMaxDistance, rhs.nMaxDistance), lhs.nMaxDepth + rhs.nMaxDepth + 2); return res; }
BinaryNode *Construct(int *preorder, int *inorder, int length){ if (preorder == NULL || inorder == NULL || length <= 0) return NULL; // 注意return NULL // 前序 - 首:尾 中序 - 首:尾 return ConstructCore(preorder, preorder + length - 1, inorder, inorder + length - 1); } BinaryNode *ConsturctCore(int *startPreorder, int *endPreorder, int * startInorder, int * endInorder){ //前序遍历第一个数字是根结点的值 int rootvalue = startPreorder[0]; BinaryNode *root = new BinaryNode();//创建结点 root->data = rootvalue; root->leftchild = root->rightchild = NULL; if (startPreorder == endPreorder){ // 边界条件 if (startInorder == endInorder && *startPreorder == *startInorder) return root; else throw std:exception("Invalid input");//非法输入 } // 在中序遍历中找到根结点的值 int *rootInorder = startInorder; while (rootInorder <= endInorder && *rootInorder != rootvalue) ++rootInorder; if (rootInorder == endInorder && *rootInorder != rootValue) throw std::exception("Invaild input"); int leftLength = rootInorder - startInorder; int *leftPreorderEnd = startPreorder + leftLength; if (leftLength > 0) //构建左子树 递归 //中序遍历后根据根节点获取的 左子树元素 rootinorder是中序遍历中的根元素的位置 root->leftchild = ConstructCore(startPreorder + 1, leftPreorderEnd, startInorder, rootInorder - 1); if (leftLength < endPreorder - startPreorder) root->rightchild = ConstructCore(leftPreorderEnd + 1, endPreorder, rootInorder, endInorder); return root; }
bool findBTree(BinaryNode *root, ElemType &x){ if (root == NULL) return false; if (root->data == x){ x = root->data; return true; } else{ if (findBTree(root->leftchild, x)) return true; if (findBTree(root->rightchild, x)) return true; return false; } }
int Count(BinaryNode *root, ElemType &x){ if (root == NULL) return -1; if (root->data == x){ return Count(root->leftchild, x) + Count(root->rightchild, x) + 1; } else return Count(root->leftchild, x) + Count(root->rightchild, x); }
int findlevel(BinaryNode *root, int x){ if (root == NULL) return -1; if (root->data == x) // 根结点的层号为1 return 1; else{ int leftlevel = findlevel(root->leftchild, x); if (leftlevel >= 1) return leftlevel + 1; int rightlevel = findlevel(root->rightchild, x); if (rightlevel >= 1) return rightlevel + 1; } else{ return -1; } }
int MaxValue(BinaryNode * root){ if (root == NULL) return 0; int leftmax, rightmax; leftmax = MaxValue(root->leftchild); rightmax = MaxValue(root->rightchild); int submax = (leftmax >= rightmax) ? leftmax : rightmax; return (submax >= root->data) ? submax : root->data; }
int TreeCount(BinaryNode *root){ if (root == NULL) return -1; else return Treecount(root->leftchild) + TreeCount(root->rightchild) + 1; }
int LeafCount(BinaryNode *root){ if (root == NULL) return -1; if (root->leftchild == NULL && root->rightchild == NULL) return 1; else return LeafCount(root->leftchild) + LeafCount(root->rightchild); }
一棵二叉树每一个结点包含一个整数,请设计一个算法输出全部知足条件的路径,此路径上全部结点的和等于定值,注意此类路径不要求必须从根结点开始post
void printbuffer(vector<int> buffer, int level, int end){ for (int i = level, i <= end; i++) cout << buffer[i] << " "; cout << endl; } // 输入:二叉树 sum定值 存储的vector<buffer> void findsum(BinaryNode *root, int sum, vector<int> buffer, int level){ if (root == NULL) return; int temp = sum; buffer.push_back(root->data); for (int i = level; i >= 0; i--){ temp -= buffer[i]; if (temp ==0) printbuffer(buffer,level,i) } findsum(root->leftchild, sum, buffer, level + 1); buffer.pop_back(); level -= 1; findsum(root->rightchild, sum, buffer, level + 1); }
// 二叉搜索树的中序遍历是递增的 int prev = INT_MIN; int judgeBST(BinaryNode *root){ int b1, b2; if (root == NULL) return 1; else{ b1 = judgeBST(root->rightchild); if (b1 == 0 || prev >= root->data) return 0; prev = root->data; b2 = judgeBST(root->rightchild); return b2; } }
// 查找是否含有key值 // 这是迭代写法 也能够递归写法 bool searchBST(BinarySortTree *root,int key){ if (root == NULL) return false; BinarySortTree *current = root; while (root != NULL){ if (key == current->data) return true; else if (key < current->data) current = current->leftchild; else current = current->rightchild; } return false; } // 插入结点 // 若是遇到重复的元素能够根据本身的定义将它归到左子树或者右子树 void insertBST(BinarySortTree *root,int key){ BinarySortTree *current = root; BinarySortTree *pre = NULL; while (current != NULL){ pre = current; if (key < current->data) current = current->leftchild; else if (key>current->data) current = current->rightchild; else return; } BinarySortTree newnode; newnode = (BinarySortTree)malloc(sizeof(BinarySortTreeNode)); newnode->data = key; newnode->leftchild = newnode->rightchild = NULL; // prev 是要安放的结点的父亲结点 if (current == NULL) current->data = key; else if (key < pre->data) pre->leftchild = newnode; else pre->rightchild = newnode; }
//后序遍历 bool isBalanced(BinaryNode* root, int *pDepth){ if (root == NULL){ *pDepth = 0; return true; } int left, right; if (isBalanced(root->leftchild, &left) && isBalanced(root->rightchild, &right)){ int diff = left - right; if (diff <= 1 && diff >= -1){ *pDepth = 1 + (left>right ? left : right); return true; } } return false; } //最大深度和最小深度的差 int maxDepth(BinaryNode *root){ if (root == NULL) return 0; return 1 + max(maxDepth(root->leftchild), maxDepth(root->rightchild)); } int minDepth(BinaryNode *root){ if (root == NULL) return 0; return 1 + min(minDepth(root->leftchild), minDepth(root->rightchild)); } bool isBalanced(BinaryNode *root){ return (maxDepth(root) - minDepth(root) <= 1); }