二叉树
非递归遍历
前序
/**
* 先序非递归遍历
* 访问一个节点时候,若该节点左右孩子节点都存在,按照右孩子左孩子顺序压栈,若只存在一个孩子节点,直接压栈该孩子节点
*/
public void firstTravel(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
//压入根节点
stack.push(root);
//栈非空,弹栈遍历该节点,然后
while (!stack.isEmpty()) {
TreeNode node = stack.pop();
System.out.print(node.val + " ");
if (node.right != null)
stack.push(node.right);
if (node.left != null)
stack.push(node.left);
}
System.out.println();
}
中序
/**
* 中序非递归遍历
* 思想:
* 左-根-右:所以只要左孩子还有左子树就要先遍历左孩子的左子树
* 1、从根节点开始将左孩子节点压栈,如果左孩子节点还有左子树继续将左孩子节点的左孩子节点压栈,一直这么持续操作,直到遇到null节点;
* 2、此时栈顶节点就是该树(不特指整棵树)中序遍历第一个要访问的节点,弹出该节点;
* 3、对该节点的右孩子节点重复1,2操作。
*/
public void inTravel(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
TreeNode node = root;
while (node != null || !stack.isEmpty()) {
//一直压入左孩子节点,直到压入null
if (node != null) {
stack.push(node);
//左孩子节点可能为null
node = node.left;
}
//栈顶元素为null就弹栈一次
else {
//此时栈顶元素就是以该栈顶元素作为根节点的树的第一个被访问节点
node = stack.pop();
System.out.print(node.val + " ");
//右孩子节点可能为null
node = node.right;
}
}
System.out.println();
}
后序
/**
* 后续遍历非递归
*/
public void lastTravel(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
TreeNode node = root;
TreeNode pre = null;//记录上一次访问的节点
while (!stack.isEmpty() || node != null) {
//一直压入左孩子节点,直到压入null
if (node != null) {
stack.push(node);
//左孩子节点可能为null,表示
node = node.left;
}
//栈顶元素为null就弹栈一次
else {
//此时栈顶元素就是以该栈顶元素作为根节点的树的第一个被访问节点
node = stack.pop();
//栈顶节点存在右孩子,且右孩子节点就是上一次被访问的节点
if (node.right == null || pre == node.right) {
System.out.print(node.val + " ");
pre = node;//更新状态
node = null;
}
//没有右孩子或者右孩子没有被访问
else {
stack.push(node);
//右孩子节点可能为null
node = node.right;
}
}
}
System.out.println();
}
层次
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> res = new ArrayList<List<Integer>>();
//we use LinkedList as a queue
LinkedList<TreeNode> q = new LinkedList<TreeNode>();
if(root == null) return res;
TreeNode p = root;
q.addLast(p);
while(!q.isEmpty()){
int tmpSize = q.size();
List<Integer> tmpList = new ArrayList<Integer>();
//Attention:i<tmpSize
for(int i=0;i<tmpSize;i++){
p = q.getFirst();
q.poll();
tmpList.add(p.val);
if(p.left!=null) q.addLast(p.left);
if(p.right!=null) q.addLast(p.right);
}
res.add(tmpList);
}
return res;
}
排序
快排
public static int partition(int[] numbers, int low,int high) {
int temp = numbers[low]; //数组的第一个作为中轴
while(low < high) {
while(low < high && numbers[high] >= temp) high--;
numbers[low] = numbers[high];//比中轴小的记录移到低端
while(low < high && numbers[low] <= temp) low++;
numbers[high] = numbers[low] ; //比中轴大的记录移到高端
}
numbers[low] = temp ; //中轴记录到尾
return low ; // 返回中轴的位置
}
public static void quickSort(int[] numbers,int low,int high) {
if(low < high) {
int middle = partition(numbers,low,high); //将numbers数组进行一分为二
quickSort(numbers, low, middle-1); //对低字段表进行递归排序
quickSort(numbers, middle+1, high); //对高字段表进行递归排序
}
}
希尔
int[] arrary = {49, 38, 65, 97, 76, 13, 27, 49, 55, 04};
int[] dk = {5, 3, 1};
public void shellInsert(int[] array, int dk) {
int temp = 0, j = 0;
// 遍历所有分组:若元素之间的距离为dk,则为同一个分组
for (int i = dk; i < array.length; i++) {
// i,i-dk为同一个分组:对同一个分组的元素进行直接插入排序
if (array[i] < array[i - dk]) {
temp = array[i];
for (j = i - dk; j >= 0 && temp < array[j]; j -= dk) {
// 后移dk
array[j + dk] = array[j];
}
// 定位
array[j + dk] = temp;
}
}
}
public void shellSort(int[] array, int[] dk, int t) {
// 依次按照分组间隔dk进行操作
for (int i = 0; i < t; i++) {
shellInsert(array, dk[i]);
}
}
归并
public void mergeSort(int[] data) {
if (data == null || data.length == 0)
return;
int len = data.length;
// 只开辟一次辅助数组
int[] temp = new int[len];
mergeSortCore(data, 0, len - 1, temp);
}
// 将两个有序子数组合并[start-mid][mid+1,end],并将排序后数组写回原数组
// temp:辅助数组
public void merge(int[] data, int start, int mid, int end, int[] temp) {
//前半段数组[start-mid];后半段数组[mid+1,end];一共为k个元素
int i = start, j = mid + 1, k = 0;
//子数组排序结果暂存于辅助数组中
while (i <= mid && j <= end) {
if (data[i] < data[j])
temp[k++] = data[i++];
else
temp[k++] = data[j++];
}
//前半段数组有剩余
while (i <= mid)
temp[k++] = data[i++];
//后半段数组有剩余
while (j <= end)
temp[k++] = data[j++];
//将排序后的子数组写回原数组
for (i = 0; i < k; i++)
data[start + i] = temp[i];
}
public void mergeSortCore(int[] data, int start, int end, int[] temp) {
//递归终止;当数组长度变为1是,停止拆分
if (start == end)
return;
//拆分为左右两个子数组
int mid = (start + end) / 2;
mergeSortCore(data, start, mid, temp);//对左侧子数组递归排序;使得左侧子数组有序
mergeSortCore(data, mid + 1, end, temp);//对右侧子数组递归排序;使得右侧子数组有序
merge(data, start, mid, end, temp);//合并当前左右有序子数组
}