日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

java tree类子项的添加和删除_使用Java实现二叉树的添加,删除,获取以及遍历...

發(fā)布時(shí)間:2024/2/28 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java tree类子项的添加和删除_使用Java实现二叉树的添加,删除,获取以及遍历... 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

二叉樹(shù)節(jié)點(diǎn)的聲明:

static final class Entry>{

//保存的數(shù)據(jù)

private T item;

//左子樹(shù)

private Entry left;

//右子樹(shù)

private Entry right;

//父節(jié)點(diǎn)

private Entry parent;

Entry(T item,Entry parent){

this.item = item;

this.parent = parent;

}

}

類(lèi)屬性:

//根節(jié)點(diǎn)

private Entry root;

//數(shù)據(jù)量

private int size = 0;

二叉樹(shù)添加數(shù)據(jù):

/**

* 添加元素

* @param item 待添加元素

* @return 已添加元素

*/

public T put(T item){

//每次添加數(shù)據(jù)的時(shí)候都是從根節(jié)點(diǎn)向下遍歷

Entry t = root;

if (t == null){

//當(dāng)前的叉樹(shù)樹(shù)的為空,將新節(jié)點(diǎn)設(shè)置為根節(jié)點(diǎn),父節(jié)點(diǎn)為null

root = new Entry<>(item,null);

size++;

return root.item;

}

//自然排序結(jié)果,如果傳入的數(shù)據(jù)小于當(dāng)前節(jié)點(diǎn)返回-1,大于當(dāng)前節(jié)點(diǎn)返回1,否則返回0

int ret = 0;

//記錄父節(jié)點(diǎn)

Entry p = t;

while (t != null){

//與當(dāng)前節(jié)點(diǎn)比較

ret = item.compareTo(t.item);

p = t;

//插入節(jié)點(diǎn)比當(dāng)前節(jié)點(diǎn)小,把當(dāng)前節(jié)點(diǎn)設(shè)置為左子節(jié)點(diǎn),然后與左子比較,以此類(lèi)推找到合適的位置

if (ret < 0)

t = t.left;

//大于當(dāng)前節(jié)點(diǎn)

else if (ret > 0)

t = t.right;

else {

//相等就把舊值覆蓋掉

t.item = item;

return t.item;

}

}

//創(chuàng)建新節(jié)點(diǎn)

Entry e = new Entry<>(item,p);

//根據(jù)比較結(jié)果將新節(jié)點(diǎn)放入合適的位置

if (ret < 0)

p.left = e;

else

p.right = e;

size++;

return e.item;

}

在put的過(guò)程中,使用Comparable中的compareTo來(lái)比較兩個(gè)元素的大小的,所以在二叉樹(shù)中存儲(chǔ)的元素必須要繼承Comparable 類(lèi),覆寫(xiě)compareTo方法。

二叉樹(shù)刪除數(shù)據(jù)

/**

* 刪除元素

* 刪除元素如果細(xì)分的話,可以分為4中:沒(méi)有子節(jié)點(diǎn),只有左節(jié)點(diǎn),只有右節(jié)點(diǎn),有兩個(gè)子節(jié)點(diǎn)

* 1)沒(méi)有子節(jié)點(diǎn)這種情況比較簡(jiǎn)單,直接刪除就可以了

* 2)只有左節(jié)點(diǎn)或右節(jié)點(diǎn),這兩種情況處理方式是一致的,只是方向相反,所以在一起講了,

* 將刪除節(jié)點(diǎn)的父節(jié)點(diǎn)的左節(jié)點(diǎn)(右節(jié)點(diǎn))指向刪除節(jié)點(diǎn)的子節(jié)點(diǎn),將左節(jié)點(diǎn)(右節(jié)點(diǎn))指向刪除節(jié)點(diǎn)的父節(jié)點(diǎn)

* 3)有兩個(gè)子節(jié)點(diǎn),這種情況相對(duì)來(lái)說(shuō)比較復(fù)雜一點(diǎn):

* 找到刪除節(jié)點(diǎn)的前驅(qū)節(jié)點(diǎn)或后繼節(jié)點(diǎn),然后將前驅(qū)或后繼節(jié)點(diǎn)的值賦給刪除節(jié)點(diǎn),然后將前驅(qū)或后繼節(jié)點(diǎn)刪除。本質(zhì)是刪除前驅(qū)或后繼節(jié)點(diǎn)

* 前驅(qū)節(jié)點(diǎn)的特點(diǎn):

* 1)刪除的左子節(jié)點(diǎn)沒(méi)有右子節(jié)點(diǎn),那么左子節(jié)點(diǎn)即為前驅(qū)節(jié)點(diǎn)

* 2)刪除節(jié)點(diǎn)的左子節(jié)點(diǎn)有右子節(jié)點(diǎn),那么最右邊的最后一個(gè)節(jié)點(diǎn)即為前驅(qū)節(jié)點(diǎn)

* 后繼節(jié)點(diǎn)的特點(diǎn):

* 與前驅(qū)節(jié)點(diǎn)剛好相反,總是右子節(jié)點(diǎn),或則右子節(jié)點(diǎn)的最左子節(jié)點(diǎn);例如:刪除節(jié)點(diǎn)為c ,那么前驅(qū)節(jié)點(diǎn)為 m,后繼節(jié)點(diǎn)為n

* a

* / \

* b c

* / \ / \

* d e f g

* / \ / \ / \ / \

* @param item 刪除元素 h i j k l m n o

* @return 刪除結(jié)果

*/

public boolean remove(T item){

//獲取刪除節(jié)點(diǎn)

Entry delEntry = getEntry(item);

if (delEntry == null) return false;

//刪除節(jié)點(diǎn)的父節(jié)點(diǎn)

Entry p = delEntry.parent;

size--;

//情況1:沒(méi)有子節(jié)點(diǎn)

if (delEntry.left == null && delEntry.right == null){

//刪除節(jié)點(diǎn)為根節(jié)點(diǎn)

if (delEntry == root){

root = null;

}else {//非根節(jié)點(diǎn)

//刪除的是父節(jié)點(diǎn)的左節(jié)點(diǎn)

if (delEntry == p.left){

p.left = null;

}else {//刪除右節(jié)點(diǎn)

p.right = null;

}

}

//情況2:刪除的節(jié)點(diǎn)只有左節(jié)點(diǎn)

}else if (delEntry.right == null){

Entry lc = delEntry.left;

//刪除的節(jié)點(diǎn)為根節(jié)點(diǎn),將刪除節(jié)點(diǎn)的左節(jié)點(diǎn)設(shè)置成根節(jié)點(diǎn)

if (p == null) {

lc.parent = null;

root = lc;

} else {//非根節(jié)點(diǎn)

if (delEntry == p.left){//刪除左節(jié)點(diǎn)

p.left = lc;

}else {//刪除右節(jié)點(diǎn)

p.right = lc;

}

lc.parent = p;

}

//情況3:刪除節(jié)點(diǎn)只有右節(jié)點(diǎn)

}else if (delEntry.left == null){

Entry rc = delEntry.right;

//刪除根節(jié)點(diǎn)

if (p == null) {

rc.parent = null;

root = rc;

}else {//刪除非根節(jié)點(diǎn)

if (delEntry == p.left)

p.left = rc;

else

p.right = rc;

rc.parent = p;

}

//情況4:刪除節(jié)點(diǎn)有兩個(gè)子節(jié)點(diǎn)

}else {//有兩個(gè)節(jié)點(diǎn),找到后繼節(jié)點(diǎn),將值賦給刪除節(jié)點(diǎn),然后將后繼節(jié)點(diǎn)刪除掉即可

Entry successor = successor(delEntry);//獲取到后繼節(jié)點(diǎn)

delEntry.item = successor.item;

//后繼節(jié)點(diǎn)為右子節(jié)點(diǎn)

if (delEntry.right == successor){

//右子節(jié)點(diǎn)有右子節(jié)點(diǎn)

if (successor.right != null) {

delEntry.right = successor.right;

successor.right.parent = delEntry;

}else {//右子節(jié)點(diǎn)沒(méi)有子節(jié)點(diǎn)

delEntry.right = null;

}

}else {//后繼節(jié)點(diǎn)必定是左節(jié)點(diǎn)

successor.parent.left = null;

}

return true;

}

//讓gc回收

delEntry.parent = null;

delEntry.left = null;

delEntry.right = null;

return true;

}

/**

* 獲取節(jié)點(diǎn)節(jié)點(diǎn)

* @param item 獲取節(jié)點(diǎn)

* @return 獲取到的節(jié)點(diǎn),可能為null

*/

private Entry getEntry(T item){

Entry t = root;

int ret;

//從根節(jié)點(diǎn)開(kāi)始遍歷

for (;t != null;){

ret = item.compareTo(t.item);

if (ret < 0)

t = t.left;

else if (ret > 0)

t = t.right;

else

return t;

}

return null;

}

/**

* 查找后繼節(jié)點(diǎn)

* @param delEntry 刪除節(jié)點(diǎn)

* @return 后繼節(jié)點(diǎn)

*/

private Entry successor(Entry delEntry) {

Entry r = delEntry.right;//r節(jié)點(diǎn)必定不為空

while (r.left != null){

r = r.left;

}

return r;

}

二叉樹(shù)獲取節(jié)點(diǎn)

/**

* 判斷是否存在該元素

* @param item 查找元素

* @return 結(jié)果

*/

public boolean contains(T item){

return getEntry(item) != null;

}

/**

* 獲取節(jié)點(diǎn)節(jié)點(diǎn)

* @param item 獲取節(jié)點(diǎn)

* @return 獲取到的節(jié)點(diǎn),可能為null

*/

private Entry getEntry(T item){

Entry t = root;

int ret;

//從根節(jié)點(diǎn)開(kāi)始遍歷

for (;t != null;){

ret = item.compareTo(t.item);

if (ret < 0)

t = t.left;

else if (ret > 0)

t = t.right;

else

return t;

}

return null;

}

因?yàn)槲疫@個(gè)例子是存儲(chǔ)一個(gè)元素,獲取到的元素和傳進(jìn)去的元素是一致的,所以我用contains方法來(lái)判斷返回true即表示獲取成功了,不返回獲取到的結(jié)果了。當(dāng)然,如果將entry存儲(chǔ)的元素改為kv形式的話,就可以使用get方法了。

二叉樹(shù)的遍歷

二叉樹(shù)的遍歷可以分為三種:前序遍歷、中序遍歷和后續(xù)遍歷,其中中序遍歷是最常用的遍歷方式,因?yàn)樗闅v出來(lái)的結(jié)果的升序的。

前序遍歷:

/**

* 前序遍歷

* @param e 開(kāi)始遍歷元素

*/

public void prevIterator(Entry e){

if (e != null) {

System.out.print(e.item + " ");

prevIterator(e.left);

prevIterator(e.right);

}

}

中序遍歷:

/**

* 中序遍歷

* @param e

*/

public void midIterator(Entry e){

if (e != null){

midIterator(e.left);

System.out.print(e.item + " ");

midIterator(e.right);

}

}

后序遍歷:

/**

* 后續(xù)遍歷

* @param e 開(kāi)始遍歷元素

*/

public void subIterator(Entry e){

if (e != null) {

subIterator(e.left);

subIterator(e.right);

System.out.print(e.item + " ");

}

}

package com.rainple.collections;

/**

* 二叉樹(shù)

* @param

*/

public class BinaryTree> {

//根節(jié)點(diǎn)

private Entry root;

//數(shù)據(jù)量

private int size = 0;

public BinaryTree(){}

/**

* 添加元素

* @param item 待添加元素

* @return 已添加元素

*/

public T put(T item){

//每次添加數(shù)據(jù)的時(shí)候都是從根節(jié)點(diǎn)向下遍歷

Entry t = root;

size++;

if (t == null){

//當(dāng)前的叉樹(shù)樹(shù)的為空,將新節(jié)點(diǎn)設(shè)置為根節(jié)點(diǎn),父節(jié)點(diǎn)為null

root = new Entry<>(item,null);

return root.item;

}

//自然排序結(jié)果,如果傳入的數(shù)據(jù)小于當(dāng)前節(jié)點(diǎn)返回-1,大于當(dāng)前節(jié)點(diǎn)返回1,否則返回0

int ret = 0;

//記錄父節(jié)點(diǎn)

Entry p = t;

while (t != null){

//與當(dāng)前節(jié)點(diǎn)比較

ret = item.compareTo(t.item);

p = t;

//插入節(jié)點(diǎn)比當(dāng)前節(jié)點(diǎn)小,把當(dāng)前節(jié)點(diǎn)設(shè)置為左子節(jié)點(diǎn),然后與左子比較,以此類(lèi)推找到合適的位置

if (ret < 0)

t = t.left;

//大于當(dāng)前節(jié)點(diǎn)

else if (ret > 0)

t = t.right;

else {

//相等就把舊值覆蓋掉

t.item = item;

return t.item;

}

}

//創(chuàng)建新節(jié)點(diǎn)

Entry e = new Entry<>(item,p);

//根據(jù)比較結(jié)果將新節(jié)點(diǎn)放入合適的位置

if (ret < 0)

p.left = e;

else

p.right = e;

return e.item;

}

public void print(){

midIterator(root);

}

/**

* 中序遍歷

* @param e

*/

public void midIterator(Entry e){

if (e != null){

midIterator(e.left);

System.out.print(e.item + " ");

midIterator(e.right);

}

}

/**

* 獲取根節(jié)點(diǎn)

* @return 根節(jié)點(diǎn)

*/

public Entry getRoot(){return root;}

/**

* 前序遍歷

* @param e 開(kāi)始遍歷元素

*/

public void prevIterator(Entry e){

if (e != null) {

System.out.print(e.item + " ");

prevIterator(e.left);

prevIterator(e.right);

}

}

/**

* 后續(xù)遍歷

* @param e 開(kāi)始遍歷元素

*/

public void subIterator(Entry e){

if (e != null) {

subIterator(e.left);

subIterator(e.right);

System.out.print(e.item + " ");

}

}

/**

* 獲取節(jié)點(diǎn)節(jié)點(diǎn)

* @param item 獲取節(jié)點(diǎn)

* @return 獲取到的節(jié)點(diǎn),可能為null

*/

private Entry getEntry(T item){

Entry t = root;

int ret;

//從根節(jié)點(diǎn)開(kāi)始遍歷

for (;t != null;){

ret = item.compareTo(t.item);

if (ret < 0)

t = t.left;

else if (ret > 0)

t = t.right;

else

return t;

}

return null;

}

/**

* 判斷是否存在該元素

* @param item 查找元素

* @return 結(jié)果

*/

public boolean contains(T item){

return getEntry(item) != null;

}

/**

* 刪除元素

* 刪除元素如果細(xì)分的話,可以分為4中:沒(méi)有子節(jié)點(diǎn),只有左節(jié)點(diǎn),只有右節(jié)點(diǎn),有兩個(gè)子節(jié)點(diǎn)

* 1)沒(méi)有子節(jié)點(diǎn)這種情況比較簡(jiǎn)單,直接刪除就可以了

* 2)只有左節(jié)點(diǎn)或右節(jié)點(diǎn),這兩種情況處理方式是一致的,只是方向相反,所以在一起講了,

* 將刪除節(jié)點(diǎn)的父節(jié)點(diǎn)的左節(jié)點(diǎn)(右節(jié)點(diǎn))指向刪除節(jié)點(diǎn)的子節(jié)點(diǎn),將左節(jié)點(diǎn)(右節(jié)點(diǎn))指向刪除節(jié)點(diǎn)的父節(jié)點(diǎn)

* 3)有兩個(gè)子節(jié)點(diǎn),這種情況相對(duì)來(lái)說(shuō)比較復(fù)雜一點(diǎn):

* 找到刪除節(jié)點(diǎn)的前驅(qū)節(jié)點(diǎn)或后繼節(jié)點(diǎn),然后將前驅(qū)或后繼節(jié)點(diǎn)的值賦給刪除節(jié)點(diǎn),然后將前驅(qū)或后繼節(jié)點(diǎn)刪除。本質(zhì)是刪除前驅(qū)或后繼節(jié)點(diǎn)

* 前驅(qū)節(jié)點(diǎn)的特點(diǎn):

* 1)刪除的左子節(jié)點(diǎn)沒(méi)有右子節(jié)點(diǎn),那么左子節(jié)點(diǎn)即為前驅(qū)節(jié)點(diǎn)

* 2)刪除節(jié)點(diǎn)的左子節(jié)點(diǎn)有右子節(jié)點(diǎn),那么最右邊的最后一個(gè)節(jié)點(diǎn)即為前驅(qū)節(jié)點(diǎn)

* 后繼節(jié)點(diǎn)的特點(diǎn):

* 與前驅(qū)節(jié)點(diǎn)剛好相反,總是右子節(jié)點(diǎn),或則右子節(jié)點(diǎn)的最左子節(jié)點(diǎn);例如:刪除節(jié)點(diǎn)為c ,那么前驅(qū)節(jié)點(diǎn)為 m,后繼節(jié)點(diǎn)為n

* a

* / \

* b c

* / \ / \

* d e f g

* / \ / \ / \ / \

* @param item 刪除元素 h i j k l m n o

* @return 刪除結(jié)果

*/

public boolean remove(T item){

//獲取刪除節(jié)點(diǎn)

Entry delEntry = getEntry(item);

if (delEntry == null) return false;

//刪除節(jié)點(diǎn)的父節(jié)點(diǎn)

Entry p = delEntry.parent;

size--;

//情況1:沒(méi)有子節(jié)點(diǎn)

if (delEntry.left == null && delEntry.right == null){

//刪除節(jié)點(diǎn)為根節(jié)點(diǎn)

if (delEntry == root){

root = null;

}else {//非根節(jié)點(diǎn)

//刪除的是父節(jié)點(diǎn)的左節(jié)點(diǎn)

if (delEntry == p.left){

p.left = null;

}else {//刪除右節(jié)點(diǎn)

p.right = null;

}

}

//情況2:刪除的節(jié)點(diǎn)只有左節(jié)點(diǎn)

}else if (delEntry.right == null){

Entry lc = delEntry.left;

//刪除的節(jié)點(diǎn)為根節(jié)點(diǎn),將刪除節(jié)點(diǎn)的左節(jié)點(diǎn)設(shè)置成根節(jié)點(diǎn)

if (p == null) {

lc.parent = null;

root = lc;

} else {//非根節(jié)點(diǎn)

if (delEntry == p.left){//刪除左節(jié)點(diǎn)

p.left = lc;

}else {//刪除右節(jié)點(diǎn)

p.right = lc;

}

lc.parent = p;

}

//情況3:刪除節(jié)點(diǎn)只有右節(jié)點(diǎn)

}else if (delEntry.left == null){

Entry rc = delEntry.right;

//刪除根節(jié)點(diǎn)

if (p == null) {

rc.parent = null;

root = rc;

}else {//刪除非根節(jié)點(diǎn)

if (delEntry == p.left)

p.left = rc;

else

p.right = rc;

rc.parent = p;

}

//情況4:刪除節(jié)點(diǎn)有兩個(gè)子節(jié)點(diǎn)

}else {//有兩個(gè)節(jié)點(diǎn),找到后繼節(jié)點(diǎn),將值賦給刪除節(jié)點(diǎn),然后將后繼節(jié)點(diǎn)刪除掉即可

Entry successor = successor(delEntry);//獲取到后繼節(jié)點(diǎn)

delEntry.item = successor.item;

//后繼節(jié)點(diǎn)為右子節(jié)點(diǎn)

if (delEntry.right == successor){

//右子節(jié)點(diǎn)有右子節(jié)點(diǎn)

if (successor.right != null) {

delEntry.right = successor.right;

successor.right.parent = delEntry;

}else {//右子節(jié)點(diǎn)沒(méi)有子節(jié)點(diǎn)

delEntry.right = null;

}

}else {//后繼節(jié)點(diǎn)必定是左節(jié)點(diǎn)

successor.parent.left = null;

}

return true;

}

//讓gc回收

delEntry.parent = null;

delEntry.left = null;

delEntry.right = null;

return true;

}

/**

* 查找后繼節(jié)點(diǎn)

* @param delEntry 刪除節(jié)點(diǎn)

* @return 后繼節(jié)點(diǎn)

*/

private Entry successor(Entry delEntry) {

Entry r = delEntry.right;//r節(jié)點(diǎn)必定不為空

while (r.left != null){

r = r.left;

}

return r;

}

public int size(){return size;}

public boolean isEmpty(){return size == 0;}

public void clear(){

clear(getRoot());

root = null;

}

private void clear(Entry e){

if (e != null){

clear(e.left);

e.left = null;

clear(e.right);

e.right = null;

}

}

static final class Entry>{

//保存的數(shù)據(jù)

private T item;

//左子樹(shù)

private Entry left;

//右子樹(shù)

private Entry right;

//父節(jié)點(diǎn)

private Entry parent;

Entry(T item,Entry parent){

this.item = item;

this.parent = parent;

}

}

}

測(cè)試代碼示例:

public static void main(String[] args) {

BinaryTree binaryTree = new BinaryTree<>();

//放數(shù)據(jù)

binaryTree.put(73);

binaryTree.put(22);

binaryTree.put(532);

binaryTree.put(62);

binaryTree.put(72);

binaryTree.put(243);

binaryTree.put(42);

binaryTree.put(3);

binaryTree.put(12);

binaryTree.put(52);

System.out.println("size: " + binaryTree.size());

binaryTree.put(52);

System.out.println("添加相同元素后的size: " + binaryTree.size());

//判斷數(shù)據(jù)是否存在

System.out.println("數(shù)據(jù)是否存在:" + binaryTree.contains(12));

//中序遍歷

System.out.print("中序遍歷結(jié)果: ");

binaryTree.midIterator(binaryTree.getRoot());

System.out.println();

//前序遍歷

System.out.print("前遍歷結(jié)果: ");

binaryTree.prevIterator(binaryTree.getRoot());

System.out.println();

//后序遍歷

System.out.print("后續(xù)遍歷結(jié)果: ");

binaryTree.subIterator(binaryTree.getRoot());

//刪除數(shù)據(jù)

System.out.println();

binaryTree.remove(62);

System.out.println("刪除數(shù)據(jù)后判斷是否存在:" + binaryTree.contains(62));

//清空二叉樹(shù)

binaryTree.clear();

System.out.print("清空數(shù)據(jù)后中序遍歷: ");

binaryTree.midIterator(binaryTree.getRoot());

}

測(cè)試結(jié)果:

size: 10

添加相同元素后的size: 10

數(shù)據(jù)是否存在:true

中序遍歷結(jié)果: 3 12 22 42 52 62 72 73 243 532

前遍歷結(jié)果: 73 22 3 12 62 42 52 72 532 243

后續(xù)遍歷結(jié)果: 12 3 52 42 72 62 22 243 532 73

刪除數(shù)據(jù)后判斷是否存在:false

總結(jié)

以上是生活随笔為你收集整理的java tree类子项的添加和删除_使用Java实现二叉树的添加,删除,获取以及遍历...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。