链表 是动态地进行存储分配的一种数据结构(单链表和双向链表)
双向链表添加元素:
// 添加元素
public void add(E item) {
// 创建节点,存入数据
MyNode<E> myNode = new MyNode<E>(item);
if (first == null) {
first = myNode;
first.next = null;
first.pre = null;
}
if (last != null) {
last.next = myNode;
myNode.pre = last;
}
last = myNode;
size++;
}
public void add(E item) {
// 创建节点,存入数据
MyNode<E> myNode = new MyNode<E>(item);
if (first == null) {
first = myNode;
first.next = null;
first.pre = null;
}
if (last != null) {
last.next = myNode;
myNode.pre = last;
}
last = myNode;
size++;
}
双向链表删除元素:
// 删除元素
public E remove(int index) {
if (index < 0 || index > size) {
try {
throw new Exception("角标越界");
} catch (Exception e) {
e.printStackTrace();
}
}
// 初始结果值
E result = null;
// 遍历到要删除元素的前一个
MyNode<E> before = first;
for (int i = 0; i < index - 1; i++) {
before = before.next;
}
if (index == 0) { // 删除头部
result = first.item;
first = first.next;
first.pre = null;
} else if (index == size - 1) { // 删除尾部
// 最后一个元素赋值给结果值
result = last.item;
before.next = null;
last = before;
} else { // 删除中间
// 找到当前要删除的节点
MyNode<E> current = before.next;
result = current.item;
before.next = current.next;
current = null;
}
size--;
return result;
}
public E remove(int index) {
if (index < 0 || index > size) {
try {
throw new Exception("角标越界");
} catch (Exception e) {
e.printStackTrace();
}
}
// 初始结果值
E result = null;
// 遍历到要删除元素的前一个
MyNode<E> before = first;
for (int i = 0; i < index - 1; i++) {
before = before.next;
}
if (index == 0) { // 删除头部
result = first.item;
first = first.next;
first.pre = null;
} else if (index == size - 1) { // 删除尾部
// 最后一个元素赋值给结果值
result = last.item;
before.next = null;
last = before;
} else { // 删除中间
// 找到当前要删除的节点
MyNode<E> current = before.next;
result = current.item;
before.next = current.next;
current = null;
}
size--;
return result;
}
双向链表插入元素:
// 插入元素
public void insert(int index, E data) {
// 判断角标是否越界
if (index < 0 || index > size) {
try {
throw new Exception("角标越界");
} catch (Exception e) {
e.printStackTrace();
}
}
// 遍历到要插入的前一个节点
MyNode<E> before = first;
for (int i = 0; i < index - 1; i++) {
before = before.next;
}
// 构建要插入的节点
MyNode<E> myNode = new MyNode<E>(data);
if (index == 0) {
myNode.next = before;
before.pre = myNode;
first = myNode;
size++;
} else {
myNode.next = before;
before.pre = myNode;
before.next = myNode;
myNode.pre = before;
}
}
public void insert(int index, E data) {
// 判断角标是否越界
if (index < 0 || index > size) {
try {
throw new Exception("角标越界");
} catch (Exception e) {
e.printStackTrace();
}
}
// 遍历到要插入的前一个节点
MyNode<E> before = first;
for (int i = 0; i < index - 1; i++) {
before = before.next;
}
// 构建要插入的节点
MyNode<E> myNode = new MyNode<E>(data);
if (index == 0) {
myNode.next = before;
before.pre = myNode;
first = myNode;
size++;
} else {
myNode.next = before;
before.pre = myNode;
before.next = myNode;
myNode.pre = before;
}
}
获取元素:
//获取元素
public E get(int index) {
if (index < 0 || index > size) {
try {
throw new Exception("角标越界");
} catch (Exception e) {
e.printStackTrace();
}
}
MyNode<E> result = first;
for (int i = 0; i < index; i++) {
result = result.next;
}
return result.item;
}
if (index < 0 || index > size) {
try {
throw new Exception("角标越界");
} catch (Exception e) {
e.printStackTrace();
}
}
MyNode<E> result = first;
for (int i = 0; i < index; i++) {
result = result.next;
}
return result.item;
}
定义节点:
public class MyNode<E> {
// 定义双项列表节点指针
MyNode<E> next;
MyNode<E> pre;
// 定义数据
E item;
public MyNode(E item) {
this.item = item;
}
}
// 定义双项列表节点指针
MyNode<E> next;
MyNode<E> pre;
// 定义数据
E item;
public MyNode(E item) {
this.item = item;
}
}
树
是由n(n>=1)个有限节点组成一个具有层次关系的集合
![]()
树的术语:
节点度:一个节点含有子树的个数称为该节点的度
树的度:一棵树中,最大的节点的度为树的度
叶子节点:度为零的节点
父亲节点:若一个节点含有子节点,则当前节点为改子节点的父亲节点
子节点:一个节点含有子树,则子树的根节点为改节点的子节点
兄弟节点:具有相同父亲节点的子节点互为兄弟节点
节点层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推
树的深度(高度):树中节点最大的层次
其他:堂兄弟节点、子孙、森林
树的分类:
无序树:树中的节点次序是没有规律的
有序树:指树中同层结点从左到右有次序排列,这样的树称为有序树。
1)二叉树:每个节点最多含有两个子树的树称为二叉树
2)非二叉树:所有不是二叉树的树都属于非二叉树
树的遍历:
先序遍历树
先访问根节点,然后访问左子树,最后访问右子树
中序遍历树
先访问左子树,然后访问根节点,最后访问右子树
后续遍历树
先访问左子树,然后访问右子树,最后访问
二叉树是由一个根结点、两棵互不相交的左子树和右子树组成
完全二叉树性质
1、若根结点的层次为
1
,则二叉树第
i
层最多有
2
的(i-1)次方个结点。
2、在高度为
k
的二叉树中,则最多有
2
k
-
1
个结点(
k≥0
)
3、设一棵二叉树节点个数为n,则父节点个数为n/2。
4、一棵具有
n
个结点的完全二叉树,对序号为
i
(
0≤i<n
)的结点,则:
5、若i=0,则i为根结点,无父母结点;若i >0,则i的左右子结点序号为:
•
若
2i+1<n
,则
i
的左孩子结点序号为
2i+1
;否则
i
无左孩子。
•
若
2i+2<n
,则
i
的右孩子结点序号为
2i+2
;否则
i
无右孩子。
例:二叉树的遍历
package czm.tree;
import java.util.ArrayList;
public class CreateTree {
int[] arr;
ArrayList<TreeNode> list = new ArrayList<TreeNode>();
public CreateTree(int[] arr) {
this.arr = arr;
}
// 构建树
public TreeNode createTree() {
// 封装数组中元素节点
for (int i = 0; i < arr.length; i++) {
TreeNode treeNode = new TreeNode(arr[i]);
// 构建森林
list.add(treeNode);
}
// 构建二叉树,遍历森林中的父节点
for (int i = 0; i < list.size() / 2 - 1; i++) {
// 构建所有父节点左右孩子
list.get(i).setLeft(list.get(2 * i + 1));
list.get(i).setRight(list.get(2 * i + 2));
}
// 单独处理最后一个节点
int lastIndex = list.size() / 2 - 1;
TreeNode treeNode = list.get(lastIndex);
treeNode.setLeft(list.get(2 * lastIndex + 1));
if (list.size() % 2 == 1) {
// 满二叉树
treeNode.setRight(list.get(lastIndex + 2));
}
return list.get(0);
}
// 前序遍历
public void preSearch(TreeNode root) {
// 根
System.out.println(root.getValue());
// 左
if (root.getLeft() != null) {
preSearch(root.getLeft());
}
// 右
if (root.getRight() != null) {
preSearch(root.getRight());
}
}
// 中序遍历
public void midSearch(TreeNode root) {
// 左
if (root.getLeft() != null) {
midSearch(root.getLeft());
}
// 根
System.out.println(root.getValue());
// 右
if (root.getRight() != null) {
midSearch(root.getRight());
}
}
// 后序遍历
public void lastSearch(TreeNode root) {
// 左
if (root.getLeft() != null) {
lastSearch(root.getLeft());
}
// 右
if (root.getRight() != null) {
lastSearch(root.getRight());
}
// 中
System.out.println(root.getValue());
}
public static void main(String[] args) {
int[] arr = { 23, 11, 22, 4, 9, 33, 36 };
CreateTree ct = new CreateTree(arr);
TreeNode createTree = ct.createTree();
ct.lastSearch(createTree);
}
}
树的术语:
节点度:一个节点含有子树的个数称为该节点的度
树的度:一棵树中,最大的节点的度为树的度
叶子节点:度为零的节点
父亲节点:若一个节点含有子节点,则当前节点为改子节点的父亲节点
子节点:一个节点含有子树,则子树的根节点为改节点的子节点
兄弟节点:具有相同父亲节点的子节点互为兄弟节点
节点层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推
树的深度(高度):树中节点最大的层次
其他:堂兄弟节点、子孙、森林
树的分类:
无序树:树中的节点次序是没有规律的
有序树:指树中同层结点从左到右有次序排列,这样的树称为有序树。
1)二叉树:每个节点最多含有两个子树的树称为二叉树
2)非二叉树:所有不是二叉树的树都属于非二叉树
树的遍历:
先序遍历树
先访问根节点,然后访问左子树,最后访问右子树
中序遍历树
先访问左子树,然后访问根节点,最后访问右子树
后续遍历树
先访问左子树,然后访问右子树,最后访问
二叉树是由一个根结点、两棵互不相交的左子树和右子树组成
完全二叉树性质
1、若根结点的层次为
1
,则二叉树第
i
层最多有
2
的(i-1)次方个结点。
2、在高度为
k
的二叉树中,则最多有
2
k
-
1
个结点(
k≥0
)
3、设一棵二叉树节点个数为n,则父节点个数为n/2。
4、一棵具有
n
个结点的完全二叉树,对序号为
i
(
0≤i<n
)的结点,则:
5、若i=0,则i为根结点,无父母结点;若i >0,则i的左右子结点序号为:
•
若
2i+1<n
,则
i
的左孩子结点序号为
2i+1
;否则
i
无左孩子。
•
若
2i+2<n
,则
i
的右孩子结点序号为
2i+2
;否则
i
无右孩子。
import java.util.ArrayList;
public class CreateTree {
int[] arr;
ArrayList<TreeNode> list = new ArrayList<TreeNode>();
public CreateTree(int[] arr) {
this.arr = arr;
}
// 构建树
public TreeNode createTree() {
// 封装数组中元素节点
for (int i = 0; i < arr.length; i++) {
TreeNode treeNode = new TreeNode(arr[i]);
// 构建森林
list.add(treeNode);
}
// 构建二叉树,遍历森林中的父节点
for (int i = 0; i < list.size() / 2 - 1; i++) {
// 构建所有父节点左右孩子
list.get(i).setLeft(list.get(2 * i + 1));
list.get(i).setRight(list.get(2 * i + 2));
}
// 单独处理最后一个节点
int lastIndex = list.size() / 2 - 1;
TreeNode treeNode = list.get(lastIndex);
treeNode.setLeft(list.get(2 * lastIndex + 1));
if (list.size() % 2 == 1) {
// 满二叉树
treeNode.setRight(list.get(lastIndex + 2));
}
return list.get(0);
}
// 前序遍历
public void preSearch(TreeNode root) {
// 根
System.out.println(root.getValue());
// 左
if (root.getLeft() != null) {
preSearch(root.getLeft());
}
// 右
if (root.getRight() != null) {
preSearch(root.getRight());
}
}
// 中序遍历
public void midSearch(TreeNode root) {
// 左
if (root.getLeft() != null) {
midSearch(root.getLeft());
}
// 根
System.out.println(root.getValue());
// 右
if (root.getRight() != null) {
midSearch(root.getRight());
}
}
// 后序遍历
public void lastSearch(TreeNode root) {
// 左
if (root.getLeft() != null) {
lastSearch(root.getLeft());
}
// 右
if (root.getRight() != null) {
lastSearch(root.getRight());
}
// 中
System.out.println(root.getValue());
}
public static void main(String[] args) {
int[] arr = { 23, 11, 22, 4, 9, 33, 36 };
CreateTree ct = new CreateTree(arr);
TreeNode createTree = ct.createTree();
ct.lastSearch(createTree);
}
}