1 单向链表反转
1.1 思路
单向链表反转其实是把每个节点的指针域由原来的指向下一个节点,变为指向前一个节点。
- 需要三个变量,前驱结点preNode,当前节点curNode,下一个节点nextNode。
- 遍历单链表
- nextNode指向curNode.next
- curNode的指针域指向前一个节点
- preNode指向curNode
- curtNode指向nextNode 直到遍历到最后一个节点为止。
- 返回preNode
1.2 代码
public class Node {
private Object data;//数据域
private Node next;//指针域
public Node(Object data){
this.data = data;
}
public Node(Object data,Node next){
this.data = data;
this.next = next;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}
public static Node reverseListNode(Node head){
//单链表为空或只有一个节点,直接返回原单链表
if (head == null || head.getNext() == null){
return head;
}
//前一个节点指针
Node preNode = null;
//当前节点指针
Node curNode = head;
//下一个节点指针
Node nextNode = null;
while (curNode != null){
nextNode = curNode.getNext();//nextNode 指向下一个节点
curNode.setNext(preNode);//将当前节点next域指向前一个节点
preNode = curNode;//preNode 指针向后移动
curNode = nextNode;//curNode指针向后移动
}
return preNode;
}
2 二叉树遍历
二叉树常用的遍历方式有:前序遍历、中序遍历、后序遍历、层序遍历四种遍历方式,不同的遍历算法,其思想略有不同,我们来看一下这四种遍历方法主要的算法思想:
1、先序遍历二叉树顺序:根节点 –> 左子树 –> 右子树,即先访问根节点,然后是左子树,最后是右子树。 上图中二叉树的前序遍历结果为:0 -> 1 -> 3 -> 4 -> 2 -> 5 -> 6
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<Integer>();
if(null == root){
return result;
}
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.push(root);
while(!stack.isEmpty()){
TreeNode node = stack.pop();
result.add(node.val);
if(node.right != null){
stack.push(node.right);
}
if(node.left != null){
stack.push(node.left);
}
}
return result;
}
}
2、中序遍历二叉树顺序:左子树 –> 根节点 –> 右子树,即先访问左子树,然后是根节点,最后是右子树。
上图中二叉树的中序遍历结果为:3 -> 1 -> 4 -> 0 -> 5 -> 2 -> 6
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<Integer>();
if(null == root){
return result;
}
Stack stack = new Stack<TreeNode>();
TreeNode curNode = root;
while(curNode != null || !stack.isEmpty()){
while(curNode != null){
stack.push(curNode);
curNode = curNode.left;
}
curNode = (TreeNode)stack.pop();
result.add(curNode.val);
curNode = curNode.right;
}
return result;
}
}
3、后续遍历二叉树顺序:左子树 –> 右子树 –> 根节点,即先访问左子树,然后是右子树,最后是根节点。
上图中二叉树的后序遍历结果为:3 -> 4 -> 1 -> 5 -> 6 -> 2 -> 0
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
List<Integer> result = new ArrayList<>();
TreeNode curNode = root;
TreeNode preNode = null; //记录上一节点
while(!stack.isEmpty() || curNode != null){
while(curNode != null){
stack.push(curNode);
curNode = curNode.left;
}
curNode = stack.peek();
//后序遍历的过程中在遍历完左子树跟右子树cur都会回到根结点。所以当前不管是从左子树还是右子树回到根结点都不应该再操作了,应该退回上层。
//如果是从右边再返回根结点,应该回到上层。
//主要就是判断出来的是不是右子树,是的话就可以把根节点=加入到list了
if(curNode.right == null || curNode.right == preNode){
result.add(curNode.val);
stack.pop();
preNode = curNode;
curNode = null;
} else {
curNode = curNode.right;
}
}
return result;
}
}
4、层序遍历二叉树顺序:从最顶层的节点开始,从左往右依次遍历,之后转到第二层,继续从左往右遍历,持续循环,直到所有节点都遍历完成
上图中二叉树的层序遍历结果为:0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6