# 链表与二叉树

## 1. 链表

``````struct ListNode
{
int value;
ListNode * next;
ListNode(int x) : value(x), next(NULL) {}
};
``````

### 1.1 求单链表中结点的个数

``````int GetListLenght(ListNode* head)
{
int len = 0;
while(current != NULL)
{
len++;
current = current->next;
}
return len;
}
``````

### 1.2 将单链表反转

``````ListNode* ReverseList(ListNode* head)
{
while(current != NULL)
{
ListNode* temp = current;
current = current->next;
}
}
``````

### 1.3 查找单链表中的倒数第K个结点（k>0）

``````ListNode * RGetKthNode(ListNode * head, unsigned int k)
{
while(k>1)
{
k--;
}
{
behind = behind->next;
}
return behind;
}
``````

### 1.4 判断一个单链表中是否有环

``````bool HasCycle(ListNode* head)
{
while(fast != NULL && fast->next != NULL)
{
fast = fast->next->next;
slow = slow->next;
if(fast == slow)    return true;
}
return false;
}
``````

### 1.5 判断一个单链表中是否有环，如果存在，求进入环中的第一个节点

``````        n6-----------n5
|              |
n1------n2----n3----n4|
``````

``````ListNode* detectCycle(ListNode* head)
{
while(fast != NULL && fast->next != NULL)
{
fast = fast->next->next;
slow = slow->next;
if(fast == slow)
{
while(slow2 != slow)
{
slow2 = slow2->next;
slow = slow->next;
}
return slow2;
}
}
return NULL;
}
``````

### 1.6 合并两个排好序的链表

``````ListNode* MergeTowList(ListNode* head1, ListNode* head2)
{
ListNode* dummy(0);
ListNode* temp = &dummy;
{
if(val1 < val2)
{
}
else
{
}
}
return dummy.next;
}
``````

### 1.7 去除有序链表中的重复元素

``````ListNode *deleteDuplicates(ListNode *head) {
if (head == nullptr) return nullptr;
for (ListNode *prev = head, *cur = head->next; cur; cur = prev->next) {
if (prev->val == cur->val) {
prev->next = cur->next;
delete cur;
}
else {
prev = cur;
}
}
}
``````

## 1. 二叉树

``````struct BinaryTreeNode
{
int value;
BinaryTreeNode* left;
BinaryTreeNode* right;
BinaryTreeNode(int x) : value(x), left(NULL), right(NULL) {}
};
``````

### 2.1 求二叉树中的结点个数

• 如果二叉树为空，节点个数为0
• 如果二叉树不为空，二叉树节点个数 = 左子树节点个数 + 右子树节点个数 + 1
``````int GetNodeNumber(BinaryTreeNode* root)
{
if(root == NULL)    return 0;
return GetNodeNumber(root->left) + GetNodeNumber(root->right) + 1;
}
``````

### 2.2 求二叉树的深度

• 如果二叉树为空，二叉树的深度为0
• 如果二叉树不为空，二叉树的深度 = max(左子树深度， 右子树深度) + 1
``````int GetDeepth(BinaryTreeNode* root)
{
if(root == NULL)    return 0;
int depthLeft = GetDeepth(root->left);
int depthRight = GetDeepth(root->right);
return depthLeft > depthRight ? (depthLeft + 1) : (depthRight + 1);
}
``````

### 2.3 前序遍历，中序遍历，后序遍历

``````void preOrderTraverse(BinaryTreeNode* root)
{
if(root == NULL)    return;
visit(root);
PreOrderTraverse(root->left); // 前序遍历左子树
PreOrderTraverse(root->right); // 前序遍历右子树
}

void InOrderTraverse(BinaryTreeNode* root)
{
if(root == NULL)    return;
InOrderTraverse(root->left); // 中序遍历左子树
visit(root); // 访问根节点
InOrderTraverse(root->right); // 中序遍历右子树
}

void PostOrderTraverse(BinaryTreeNode * root)
{
if(root == NULL)    return;
PostOrderTraverse(root->left); // 后序遍历左子树
PostOrderTraverse(root->right); // 后序遍历右子树
Visit(root); // 访问根节点
}
``````

### 2.4 层次遍历

``````void LevelTraverse(BinaryTreeNode* root)
{
if(root == NULL) return ;
queue<BinaryTreeNode*> que;
que.push(root);
while(!que.empty())
{
BinaryTreeNode* tempNode = que.front();
que.pop();
visit(tempNode);
if(root->left != NULL)    que.push(tempNode->left);
if(root->right != NULL)    que.push(tempNode->right);
}
return ;
}
``````

### 2.5 求二叉树第K层的节点个数

• 如果二叉树为空或者k<1返回0
• 如果二叉树不为空并且k==1，返回1
• 如果二叉树不为空且k>1，返回左子树中k-1层的节点个数与右子树k-1层节点个数之和
``````int GetNodeNumKthLevel(BinaryTreeNode* root, int k)
{
if(root == NULL || k<1)    return 0;
if(k == 1)    return 1;
int numLeft = GetNodeNumKthLevel(root->left, k-1);
int numRight = GetNodeNumKthLevel(root->right,k-1);
return numLeft + numRight;
}
``````

### 2.6 求二叉树中叶子节点的个数

• 如果二叉树为空，返回0；
• 如果二叉树不为空且左右子树为空，返回1；
• 如果二叉树不为空，且左右子树不同时为空，返回左子树中叶子节点个数加上右子树中叶子节点个数。
``````int GetLeafNodeNum(BinaryTreeNode * root)
{
if(root == NULL)  return 0;
if(root->left == NULL && root->right == NULL)  return 1;
int numLeft = GetLeafNodeNum(root->left); // 左子树中叶节点的个数
int numRight = GetLeafNodeNum(root->right); // 右子树中叶节点的个数
return (numLeft + numRight);
}
``````

### 2.7 判断两棵二叉树是否结构相同

• 如果两棵二叉树都为空，返回真
• 如果两棵二叉树一棵为空，另一棵不为空，返回假
• 如果两棵二叉树都不为空，如果对应的左子树和右子树都同构返回真，其他返回假
``````bool StructureCmp(BinaryTreeNode * root1, BinaryTreeNode * root2)
{
if(root1 == NULL && root2 == NULL) // 都为空，返回真
return true;
else if(root1 == NULL || root2 == NULL) // 只有一个为空，返回假
return false;
bool resultLeft = StructureCmp(root1->left, root2->left); // 比较对应左子树
bool resultRight = StructureCmp(root1->right, root2->right); // 比较对应右子树
return (resultLeft && resultRight);
}
``````

### 2.8 判断二叉树是不是平衡二叉树

• 如果二叉树为空，返回真
• 如果二叉树不为空，如果左子树和右子树都是AVL树并且左子树和右子树高度相差不大于1，返回真，其他返回假
``````bool IsAVL(BinaryTreeNode * root, int & height)
{
if(root == NULL) // 空树，返回真
{
height = 0;
return true;
}
int heightLeft;
bool resultLeft = IsAVL(root->left, heightLeft);
int heightRight;
bool resultRight = IsAVL(root->right, heightRight);
// 左子树和右子树都是AVL，并且高度相差不大于1，返回真
if(resultLeft && resultRight && abs(heightLeft - heightRight) <= 1)
{
height = max(heightLeft, heightRight) + 1;
return true;
}
else
{
height = max(heightLeft, heightRight) + 1;
return false;
}
}
``````

### 2.9 求二叉树的镜像

• 如果二叉树为空，返回空
• 如果二叉树不为空，求左子树和右子树的镜像，然后交换左子树和右子树
``````BinaryTreeNode* Mirror(BinaryTreeNode* root)
{
if(root == NULL)    return NULL;
BinaryTreeNode* mLeft = Mirror(root->left); // 求左子树镜像
BinaryTreeNode* mRight = Mirror(root->right); // 求右子树镜像
// 交换左子树和右子树
root->left = mRight;
root->right = mLeft;
return root;
}
``````

### 2.10 递归的遍历算法

``````//利用栈进行递归前序遍历
void PreorderTraversal(BinaryTreeNode* root)
{
stack<const BinaryTreeNode*> s;
if(root != NULL)    s.push(root);
while(!s.empty())
{
const BinaryTreeNode* temp = s.top();
s.pop();
visit(temp);
if(temp->right != NULL) s.push(temp->right);
if(temp->left != NULL) s.push(temp->left);
}
}

void InOrderTraversal(BinaryTreeNode* root)
{
stack<const BinaryTreeNode*> s;
const BinaryTreeNode* temp = root;
while(!s.empty() || temp !=NULL)
{
if(temp != NULL){
s.push(temp);
temp = temp->left;
}
else{
temp = s.top();
s.pop();
visit(temp);
temp = temp->right;
}
}
}

void PostOrderTraversal(BinaryTreeNode* root)
{
stack<const BinaryTreeNode*> s;
const BinaryTreeNode* temp = root, * pre = NULL;
do{
while(temp != NULL){
s.push(temp);
temp = temp->left;
}
pre = NULL;
while(!s.empty()){
temp = s.top();
s.pop();
//如果该结点的右子节点不存在或已被访问，就访问它
if(temp->right == pre){
visit(temp);
pre = temp;
}
else{
s.push(temp);
temp = temp->right;
break;
}
}
}while(!s.empty());
}
``````

### 2.11 判断是否存在一条从root到其中一个叶子节点的路径的和等于给定的值

``````bool DFS(int target, int sum, BinaryTreeNode* root)
{
if(root == NULL)    return false;
sum += root->value;
if(root->left == NULL && root->right == NULL)
{
if(sum == target)    return true;
else return false;
}
bool leftPart = DFS(target,sum,root->left);
bool rightPart = DFS(target,sum,root->right);
return leftPart || rightPart;
}

bool hasPathSum(BinaryTreeNode* root,int sum)
{
if(root == NULL)    return false;
return DFS(sum,0,root);
}
``````

### 推荐阅读更多精彩内容

• 树的概述 树是一种非常常用的数据结构，树与前面介绍的线性表，栈，队列等线性结构不同，树是一种非线性结构 1.树的定...
Jack921阅读 4,038评论 1 30
• 四、树与二叉树 1. 二叉树的顺序存储结构 二叉树的顺序存储就是用数组存储二叉树。二叉树的每个结点在顺序存储中都有...
MinoyJet阅读 1,172评论 0 7
• 1. 链表 链表是最基本的数据结构，面试官也常常用链表来考察面试者的基本能力，而且链表相关的操作相对而言比较简单，...
Mr希灵阅读 1,139评论 0 20
• 数据结构和算法--二叉树的实现 几种二叉树 1、二叉树 和普通的树相比，二叉树有如下特点： 每个结点最多只有两棵子...
sunhaiyu阅读 5,188评论 0 14
• 本文转自 http://www.cnblogs.com/manji/p/4903990.html二叉树-****你...
doublej_yjj阅读 489评论 0 8
• 《缝纫机乐队》的一切也要告一段落了，又一次被大鹏燃起来，虽然半路出家，但大鹏却也一直让我们看到了他长足的进步。从《...
玉琮21阅读 134评论 0 0
• 琉玉阅读 160评论 16 7