二叉樹時間複雜度分析及增刪改查操作java實現
順序表和連結串列的時間複雜度由給定條件不同從而會得出不同的時間複雜度結果,對於程式設計時並不總是最好用的儲存方式。二叉樹是一種更加穩定的資料儲存方式,其複雜度總是能表示為一個固定的形式。以下來分析二叉樹增刪改查操作做的時間複雜度。
設有如下資料需要進行二叉樹形式儲存:
首先對二叉樹進行基本分析:
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<find.pre.num) {
find.pre.left=null;
return find_name+"已刪除";
}
else {
find.pre.right=null;
return find_name+"已刪除";
}
}
}
else {
System.out.println("刪除失敗!");
return null;
}
}
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<arr.length;i++) {
insert(arr[i],"我是"+arr[i],root);
}
//查詢
StudentNode find=find(root,53);
System.out.println(find.name);
//修改
String change=change(root,53,"小李");
System.out.println(change);
//刪除
String delete=delete(root,14);
System.out.println(delete);
}
二叉樹是一種儲存資料比較穩定的方法,其增刪改查的時間複雜度均為log2n,但其原理實現較線性表更難理解,需要花更多精力去消化吸收。關鍵在於理解二叉樹的構造形式,牢記二叉樹的特點。