顺序表和链表的时间复杂度由给定条件不同从而会得出不同的时间复杂度结果,对于程序设计时并不总是最好用的存储方式。二叉树是一种更加稳定的数据存储方式,其复杂度总是能表示为一个固定的形式。以下来分析二叉树增删改查操作做的时间复杂度。
设有如下数据需要进行二叉树形式存储:
首先对二叉树进行基本分析:
1.二叉树每层最大容纳量为2^(n-1)个;
2.前n行共可存储1+2+4+8+···+2^(n-1)=2^n -1个数据;
3.二叉树节点分布规律是:左节点<父节点<右节点;
4.由第一层延某条路径查询到最后一层的某个数据共需要查询log2(2^n)=n次;
5.当删除某个节点时,需要将左子树最右节点或右子树最左节点移动至被删除节点处,且被移动节点的左或右节点移至被移动节点的位置。
由上述规律归纳二叉树的时间复杂度如下(以下设总结点数为n):
增:循环遍历每个节点,比较各节点的值,直到找到相应位置,时间复杂度为log2n,2为底数。
查:循环遍历每个节点,比较各节点的值,直到找到相应位置,时间复杂度为log2n。
改:循环遍历每个节点,比较各节点的值,直到找到相应位置,将此节点数据值改为相应值,时间复杂度为log2n。
删:循环遍历每个节点,比较各节点的值,直到找到相应位置,将左子树最右节点或右子树最左节点移动至被删除节点处,且被移动节点的左或右节点移至被移动节点的位置,时间复杂度为log2n。
增删改查的代码分别如下:
1.定义二叉树:
public class StudentNode {
public int num;
public String name;
public StudentNode left,right,pre;
StudentNode(){
pre=left=right=null;
}
StudentNode(int num,String name){
this.num=num;
this.name=name;
pre=left=right=null;
}
@Override
public String toString() {
return "StudentNode [num=" + num + ", name=" + name + ", left=" + left + ", right=" + right + ", pre=" + pre
+ "]";
}
}
2.增:构建包含100个不等随机数的数组,并将数据插入二叉树:
public static int[] randomCommon(int min, int max, int n){
if (n > (max - min + 1) || max < min) {
return null;
}
int[] result = new int[n];
int count = 0;
while(count < n) {
int num = (int) (Math.random() * (max - min)) + min;
boolean flag = true;
for (int j = 0; j < n; j++) {
if(num == result[j]){
flag = false;
break;
}
}
if(flag){
result[count] = num;
count++;
}
}
return result;
}
public static void insert(int num,String name,StudentNode node) {
if(num>node.num) {
StudentNode temp = new StudentNode(num,"我是第"+num);
if(node.right!=null) {
insert(num,name,node.right);
}
else
{
temp.pre=node;
node.right=temp;
}
}
else {
StudentNode temp = new StudentNode(num,"我是第"+num);
if(node.left!=null) {
insert(num,name,node.left);
}
else
{
temp.pre=node;
node.left=temp;
}
}
}
3.查:
public static StudentNode find(StudentNode root,int num) {
StudentNode point=new StudentNode();
//StudentNode copy=new StudentNode();
point=root;
while(point != null) {
if(num==point.num) {
return point;
}
else if(num>point.num) {
if(point.right==null) {
System.out.println("该学生不存在");
return null;
}
else
point=point.right;
}
else {
if(point.left==null) {
System.out.println("该学生不存在");
return null;
}
else
point=point.left;
}
}
return null;
}
4.改:
public static String change(StudentNode root,int num,String name) {
StudentNode point=new StudentNode();
point=root;
String copy;
while(point != null) {
if(num==point.num) {
copy=point.name;
point.name=name;
return "该学生原名为"+copy+",现在是"+name;
}
else if(num>point.num) {
if(point.right==null) {
return "该学生不存在";
}
else
point=point.right;
}
else {
if(point.left==null) {
return "该学生不存在";
}
else
point=point.left;
}
}
return null;
}
5.删:
public static String delete(StudentNode root,int num) {
StudentNode find=find( root,num);
StudentNode point=new StudentNode();
point=find;
if(find!=null) {
int target_num,find_num;
String target_name,find_name;
find_num=find.num;
find_name=find.name;
if(find.left!=null) {
point=find.left;
while(point.right!=null) {
point=point.right;
}
target_num=point.num;
target_name=point.name;
if(point.left!=null) {
point.pre.right=point.left;
}
find.num=target_num;
find.name=target_name;
return find_name+"已删除"+"现在由"+find.name+"取代";
}
else if(find.right!=null){
point=find.right;
while(point.left!=null) {
point=point.left;
}
target_num=point.num;
target_name=point.name;
if(point.right!=null) {
point.pre.left=point.right;
}
find.num=target_num;
find.name=target_name;
return find_name+"已删除"+"现在由"+find.name+"取代";
}
else {
if(find==root) {
find=root=null;
return find_name+"根节点已删除";
}
else if(find.num
6.main函数:
public static void main(String[] args) {
// TODO Auto-generated method stub
//增加
int[] arr = randomCommon(1,101,100);
StudentNode root = new StudentNode(1,"我是第"+1);
root.pre=null;
for(int i=1;i
二叉树是一种存储数据比较稳定的方法,其增删改查的时间复杂度均为log2n,但其原理实现较线性表更难理解,需要花更多精力去消化吸收。关键在于理解二叉树的构造形式,牢记二叉树的特点。