Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 5d84a1e

Browse files
【added】二分法,插值法,二叉查找树
1 parent a826c48 commit 5d84a1e

8 files changed

+686
-0
lines changed

‎基础知识/(5)树/二叉查找树.md

Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
### 二叉查找树,又称二叉排序树,
2+
### 一、性质:
3+
#### (1)若它的左子树不空,则左子树上所有结点的值均小于它的根结构的值
4+
#### (2)若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值
5+
#### (3)它的左右子树也分别为二叉排序树。
6+
### 它的构建详情见《大话数据结构》P315页
7+
![这里写图片描述](http://img.blog.csdn.net/20170328161103377?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvSmFja19fRnJvc3Q=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
8+
#### 定义二叉排序树先:
9+
```
10+
public class SearchTree {
11+
12+
public TreeNode root; //根结点
13+
14+
public long size; //长度
15+
}
16+
```
17+
```
18+
public class TreeNode {
19+
20+
public int data;
21+
22+
/*该节点的父节点*/
23+
public TreeNode parent;
24+
25+
/*该节点的左子节点*/
26+
public TreeNode left;
27+
28+
/*该节点的右子节点*/
29+
public TreeNode right;
30+
31+
public TreeNode(int data) {
32+
this.data = data;
33+
34+
}
35+
36+
@Override
37+
public String toString() {
38+
return "TreeNode [data=" + data + "]";
39+
}
40+
41+
}
42+
```
43+
### 二、二叉排序树查找操作:
44+
#### 大致操作:
45+
#### (1)假定二叉排序树的根结点指针为 root ,给定的关键字值为 K ,
46+
#### (2)置初值: q = root
47+
#### (3)如果 K = q -> key ,则查找成功,算法结束
48+
#### (4)否则,如果 K < q -> key ,而且 q 的左子树非空,则将 q 的左子树根送 q ,转步骤2;否则,查找失败,结束算法;
49+
#### (5) 否则,如果 K > q -> key ,而且 q 的右子树非空,则将 q 的右子树根送 q ,转步骤2;否则,查找失败,算法结束。
50+
51+
```
52+
public Node findNode(int data){
53+
if(root==null){
54+
return null;
55+
}
56+
TreeNode currentNode = root;//把根结点给到currentNode,由它开始递归
57+
while(currentNode!=null){
58+
if(currentNode.data>data){//大于data就往左子树递归找
59+
currentNode = currentNode.left;
60+
}else if(currentNode.data<data){//小于data就往右子树找
61+
currentNode = currentNode.right;
62+
}else{//找到了就返回!
63+
return currentNode;
64+
}
65+
}
66+
return null;
67+
}
68+
```
69+
### 三、插入操作:
70+
#### 在二叉排序树中插入新结点,要保证插入后的二叉树仍符合二叉排序树的定义。
71+
#### 大致过程:
72+
#### (1)若二叉排序树为空,则待插入结点S作为根结点插入到空树中;
73+
#### (2)当非空时,将待插结点关键字S->key和树根关键字t->key进行比较,若s->key = t->key,则无须插入,若s->key< t->key,则插入到根的左子树中,若s->key> t->key,则插入到根的右子树中。而子树中的插入过程和在树中的插入过程相同,如此进行下去,直到把结点*s作为一个新的树叶插入到二叉排序树中,或者直到发现树已有相同关键字的结点为止。
74+
```
75+
public Boolean addTreeNode(int data){
76+
if(null==root){
77+
root = new TreeNode(data);
78+
return true;
79+
}
80+
TreeNode treeNode = new TreeNode(data);// 即将被插入的数据
81+
TreeNode currentNode = root;
82+
TreeNode parentNode; //暂存父结点,避免遍历时操作干扰到原来的树结构
83+
while(true){
84+
parentNode = currentNode;// 保存父节点
85+
// 插入的数据比父节点小
86+
if(currentNode.data>data){
87+
currentNode = currentNode.left;//表示到父结点的左子节点
88+
if(null==currentNode){
89+
parentNode.left = treeNode;//把刚刚分配好的节点给到左子节点
90+
treeNode.parent = parentNode;//把刚刚分配好的节点中的父指针指向了父结点
91+
size++;
92+
System.out.println("数据成功插入到二叉查找树中");
93+
return true;
94+
}
95+
}else if(currentNode.data<data){
96+
currentNode = currentNode.right;//表示到父结点的右子节点
97+
// 当前父节点的右子节点为空
98+
if (null == currentNode) {
99+
parentNode.right = treeNode;//把刚刚分配好的节点给到右子节点
100+
treeNode.parent = parentNode;//把刚刚分配好的节点中的父指针指向了父结点
101+
System.out.println("数据成功插入到二叉查找树中");
102+
size++;
103+
return true;
104+
}
105+
}else{
106+
System.out.println("输入数据与节点的数据相同,不再插入");
107+
return false;
108+
}
109+
}
110+
}
111+
```
112+
### 四、删除操作:
113+
#### 假设被删结点是*p,其双亲是*f,不失一般性,设*p是*f的左孩子,下面分三种情况讨论:
114+
#### 若结点*p是叶子结点,则只需修改其双亲结点*f的指针即可。也就是让它双亲节点的子节点指针至null即可。
115+
#### 若结点*p只有左子树PL或者只有右子树PR,则只要使PL或PR 成为其双亲结点的左子树即可。也就是把该节点的子节点对应上该节点的双亲节点。
116+
#### 若结点*p的左、右子树均非空,先找到*p的中序前趋(或后继)结点*s(注意*s是*p的左子树中的最右下的结点,它的右链域为空),然后有两种做法:1 令*p的左子树直接链到*p的双亲结点*f的左链上,而*p的右子树链到*p的中序前趋结点*s的右链上。2 以*p的中序前趋结点*s代替*p(即把*s的数据复制到*p中),将*s的左子树链到*s的双亲结点*q的左(或右)链上。也就是找它的一个子节点去代替被它自己的位置!
117+
```
118+
//当然在查之前还有个操作,那就是查找啦!!!接着才是删除的节点有三种,叶子节点,有一个节点的节点,有两个节点的节点。
119+
public boolean delete(int data){
120+
if(root==null){
121+
return false;
122+
}
123+
TreeNode currentNode = root;//标记当前结点
124+
TreeNode parent = root;//标记当前节点的父节点
125+
//
126+
boolean isLeftChild = false;// 这里主要是为了区分当前要删除的是左孩子还是右孩子
127+
// 显然,当current.iData == key 时,current就是需要删除的节点
128+
// 在循环中利用parent保存了父类节点,也就是以parent为父节点一层层去查
129+
while(currentNode.getData()!=data){
130+
parent = currentNode;// 在循环中利用parent保存了父类节点
131+
if(data < currentNode.data){//根据二叉查找树特点去循环,小的在左子树
132+
isLeftChild = true;
133+
currentNode = currentNode.left;
134+
}else{
135+
isLeftChild = false;
136+
currentNode = currentNode.right;
137+
}
138+
if(currentNode == null){// 找不到data时返回false
139+
return false;
140+
}
141+
}
142+
//找到后的操作:!!!
143+
// 当节点为叶子节点的时候
144+
if(currentNode.left==null&&currentNode.right==null){
145+
if(currentNode == root){//如果删的是root节点
146+
root = null;
147+
}else if(isLeftChild){//如果是左子结点
148+
parent.left =null;
149+
}else{
150+
parent.right = null;
151+
}
152+
// 当删除的节点为含有一个子节点的节点
153+
// 删除的节点只有一个左子节点时
154+
// 必须要考虑被删除的节点是左节点还是右节点
155+
}else if(currentNode.right==null){
156+
if(currentNode == root){// 要删除的节点为根节点
157+
root = currentNode.left;
158+
}else if(isLeftChild){// 要删除的节点是一个左子节点
159+
parent.left=currentNode.left;
160+
}else{// 要删除的节点是一个右子节点
161+
parent.right = currentNode.left;
162+
}
163+
// 当删除的节点为含有一个子节点的节点
164+
// 删除的节点只有一个右子节点时
165+
// 必须要考虑被删除的节点是左节点还是右节点
166+
}else if(currentNode.left==null){
167+
if(root == currentNode){ //同上
168+
root = currentNode.right;
169+
}else if(isLeftChild){
170+
parent.left = currentNode.right;
171+
}else{
172+
parent.right = currentNode.right;
173+
}
174+
}else{
175+
//首先要获取被删除节点的后继节点,currentNode。也就是说getNode里面的树形结构已经删除了的,排好序了的,(只是右边连接上,左边没有连接上)给到一个暂存Node successor那里
176+
Node successor = getNode(currentNode);
177+
if(current == root){
178+
root = successor ;
179+
//这里已经屏蔽了后继节点是叶子和非叶子节点
180+
}else if(isLeftChild){//如果被删除的是左子节点
181+
parent.left=successor;
182+
}else{//被删除的是右子节点
183+
parent.right=successor;
184+
}
185+
//最终步骤,把排好了右边序的树形结构对应上原来的左子树!
186+
successor.left=currentNode.left;
187+
188+
}
189+
return true;
190+
191+
}
192+
// 寻找后继节点,主要是当要删除的节点包含了两个子节点的时候
193+
// 返回后继节点,后继节点就是比要删除的节点的关键值要大的节点集合中的最小值。
194+
//后继节点要么是被删除节点的不包含左子节点的右节点,要么就是包含左子节点的右节点的子节点
195+
public TreeNode getNode(TreeNode delNode){
196+
// 后继节点的父节点
197+
TreeNode successorParent = delNode;
198+
// 后继节点
199+
TreeNode successor = delNode.getRight();
200+
//判断后继节点是否有左孩子
201+
TreeNode current = successor.getLeft();
202+
while (current != null) {
203+
successorParent = successor;//循环把后继节点往后移动(往左下移),直到后继结点的左子树为空。
204+
successor = current;
205+
current = current.getLeft();
206+
}
207+
//当该后继节点是属于包含左子节点的右节点的子节点。把后继结点的右子树给它的父节点,然后把后继结点移动到被删除节点位置,去替代它。因为上面的遍历后继节点的左子树必然为null
208+
if (successor != delNode.right){
209+
//后继节点的右子树给它自己的父节点(交待后事,因为自己要闪人)
210+
successorParent.left(successor.right);
211+
//把确立的后继节点连接被删除节点的右孩子
212+
successor.right(delNode.right);
213+
}
214+
return successor;
215+
}
216+
```
217+
#### 删除例子:
218+
#### 要删除的是37,结果是可以拿它的后继48来替代位置!!我们拿着图对着代码来看就懂了!!
219+
![这里写图片描述](http://img.blog.csdn.net/20170328214841165?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvSmFja19fRnJvc3Q=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
220+
![这里写图片描述](http://img.blog.csdn.net/20170328214852040?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvSmFja19fRnJvc3Q=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
File renamed without changes.
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package com.fuzhu;
2+
3+
import java.util.Scanner;
4+
5+
public class OrderSearch {
6+
7+
public static int findData(int[] arr, int n) {
8+
if (n < 1 || n > arr.length) {
9+
System.out.println("������Ų���ȷ��");
10+
}
11+
return arr[n];
12+
}
13+
public static int findDataByKey(int[] arr,int key){
14+
if(key!=0){
15+
for(int i=0;i<arr.length;i++){
16+
if(arr[i]==key){
17+
return i;
18+
}
19+
}
20+
}
21+
return -1;
22+
}
23+
24+
public static void main(String[] args) {
25+
// TODO Auto-generated method stub
26+
int[] array = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
27+
//�����
28+
// System.out.println("������Ҫ���ҵ����");
29+
// Scanner input = new Scanner(System.in);
30+
// int x = input.nextInt();
31+
// int n = findData(array,x-1);
32+
// System.out.println(n);
33+
34+
//�ؼ��ֲ���
35+
System.out.println("������Ҫ���ҵĹؼ���");
36+
Scanner input1 = new Scanner(System.in);
37+
int x1 = input1.nextInt();
38+
int n1 = findDataByKey(array,x1);
39+
System.out.println(n1+1);
40+
41+
}
42+
43+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package com.fuzhu;
2+
3+
import java.util.Scanner;
4+
/*
5+
* ��ֵ���Һ��ģ�
6+
* ��һ���й��ɵ�����õ������б������Ǹ���Ҫ���ҵĹؼ���key����ұ��������С��1⁄4�Ĺؼ��ֱȽϺ�IJ��ҷ�����
7+
*
8+
* ���Ӧ�ó�����
9+
* 1.ÿһ�ζ����ݵķ�����ͨ����ָ����ȣ����ö����൱����ġ����磬�����ҵı�һ�����ڴ��̶����ڴ��У����ÿһ�αȽ϶�
10+
Ҫ���д��̷��ʡ�
11+
* 2.���ݲ������ѱ��ź���ģ����ҳ��־��ȷֲ�������
12+
*/
13+
public class InsertSearch {
14+
//xΪҪ���ҵ�ֵ
15+
public static int Search(int[] arr,int x){
16+
int low,mid,high;
17+
low=0;
18+
high=arr.length-1;
19+
int time=0;
20+
while(low<=high){
21+
mid=low+(high-low)*(x-arr[low])/(arr[high]-arr[low]);
22+
time++;
23+
System.out.println("���� "+(time)+" ��");
24+
if(arr[mid]==x){
25+
return mid;
26+
}else if(arr[mid]>x){//С���м��1⁄4�Ĺؼ��֣������м��1⁄4��������������ң�
27+
high=mid-1;
28+
}else{//�����м��1⁄4�Ĺؼ��֣������м��1⁄4���Ұ����������ҡ�
29+
low=mid+1;
30+
}
31+
}
32+
return -1; //û�ҵ�
33+
}
34+
public static void main(String[] args) {
35+
// TODO Auto-generated method stub
36+
int[]array={1,2,3,4,5,6,7,8,9};
37+
System.out.println("������Ҫ���ҵ���");
38+
Scanner input = new Scanner(System.in);
39+
int x= input.nextInt();
40+
int n = Search(array,x);
41+
if(n<0){
42+
System.out.println("û�ҵ��������");
43+
}else{
44+
System.out.println("����λ�ڵ� "+(n+1)+" λ");
45+
}
46+
}
47+
48+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package com.fuzhu;
2+
3+
import java.util.Scanner;
4+
/*
5+
* ����˼�룺
6+
* ȡ�м�ֵ��Ϊ�Ƚ϶�����Ҫ���ҵ�ֵ���м��1⁄4�Ĺؼ�����ͬ����ҳɹ���
7+
* ��Ҫ���ҵ�ֵС���м��1⁄4�Ĺؼ��֣������м��1⁄4��������������ң�
8+
* ��Ҫ���ҵ�ֵ�����м��1⁄4�Ĺؼ��֣������м��1⁄4���Ұ����������ҡ�
9+
* �����ظ���ֱ���ҵ���û�ҵ���
10+
*/
11+
12+
public class BinarySearch {
13+
//xΪҪ���ҵ�ֵ
14+
public static int Search(int[] arr,int x){
15+
int low,mid,high;
16+
low=0;
17+
high=arr.length-1;
18+
int time=0;
19+
while(low<=high){
20+
mid=(low+high)/2;
21+
time++;
22+
System.out.println("���� "+(time)+" ��");
23+
if(arr[mid]==x){
24+
return mid;
25+
}else if(arr[mid]>x){//С���м��1⁄4�Ĺؼ��֣������м��1⁄4��������������ң�
26+
high=mid-1;
27+
}else{//�����м��1⁄4�Ĺؼ��֣������м��1⁄4���Ұ����������ҡ�
28+
low=mid+1;
29+
}
30+
}
31+
return -1; //û�ҵ�
32+
}
33+
public static void main(String[] args) {
34+
// TODO Auto-generated method stub
35+
int[]array={1,2,3,4,5,6,7,8,9};
36+
System.out.println("������Ҫ���ҵ���");
37+
Scanner input = new Scanner(System.in);
38+
int x= input.nextInt();
39+
int n = Search(array,x);
40+
if(n<0){
41+
System.out.println("û�ҵ��������");
42+
}else{
43+
System.out.println("����λ�ڵ� "+(n+1)+" λ");
44+
}
45+
}
46+
47+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//���Ҳ���������������ÿһ����㣬����Ա����ݣ����ҵ�L·�����ݾͷ��ظ��������ڽ�������
2+
CBTType TreeFindNode(CBTType treeNode,String data){ //���ҽ��.treeNodeΪ�����ҵĶ������ĸ���㣬�������dataΪ�����ҵĽ�����ݡ�
3+
//���жϸ�����Ƿ�Ϊ�գ�Ȼ�������������ݹ���ҡ������ǰ�������������������ȣ��򷵻ص�ǰ��������.
4+
CBTType ptr; //��һ���ٽ�����ĵõ���ѯ���Ľ�����ݣ�������ѯ�Ա�
5+
if(treeNode==null){
6+
return null;
7+
}
8+
else{
9+
if(treeNode.data.equals(data)){
10+
return treeNode;
11+
}
12+
else { //�ֱ������������ݹ����
13+
if((ptr=TreeFindNode(treeNode.left,data))!=null){ //�� ���������
14+
return ptr;
15+
}else if((ptr=TreeFindNode(treeNode.right,data))!=null){ //�����������
16+
return ptr;
17+
}else{
18+
return null;
19+
}
20+
}
21+
}
22+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /