链表和树

链表

   链表是一种递归的数据结构,它或者为空(null),或者是指向一个节点的引用,该节点含有一个泛型的元素和一个指向另一条链表的引用。

   在面向对象的编程中,实现链表并不困难。

public class MyNode<E> {

MyNode<E> next;

E item;

}

一个Node对象含有两个实例变量,类型分别为Item和MyNode。

Item表示值,而如果first是一个指向某个MyNode对象的变量,我们可以使用first.item和first.next访问它的实例变量。

构造链表

 根据递归定义,我们只需要一个Node类型的变量就能表示一条链表,只要保证它的值是null或者指向另一个Node对象且该对象的next域指向了另一条链表即可。

扫描二维码关注公众号,回复: 4708951 查看本文章

MyNode  first= new MyNode();

MyNode  second= new MyNode();

First.item =“a”;

Second.item = “b”;

First.next = second;

向链表中添加节点

先建立一个节点

MyNode<E> node = new MyNode<E>(item);

判断条件

if(first==null){

//如果头部为空

first = node ;

}else if(last !=null){

//如果尾部不为空

last.next = node;

}

最后size加一

last = node;

size++;

从链表中删除节点

  删除元素等要用到索引的地方,要先判断是否角标越界。

if (index < 0 || index > size) {

try {

throw new Exception("角标越界");

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

在这里可以抛出一个异常。

MyNode<E> pre = first;

E result = null;

//得到目标的前一个元素

for(int i=0;i<index-1;i++){

pre = pre.next;

}

//如果删除头部

if(index==0){

result = first.item;

first = first.next;

pre = null;

}

//如果删除尾部

else if(index==size-1){

result = last.item;

pre.next = null;

last = pre;

}

//如果删除中间的

else{

MyNode<E> self = pre.next;

result = self.item;

pre.next = self.next;

self = null;

}

size--;

return result;

向链表中插入节点

MyNode<E> node = new MyNode<E>(item);

MyNode<E> pre = first;

for(int i=0;i<index1;i++){

pre = pre.next;

}

 //这里判断是否在头部插入

 if(index2==0) {

          node.next = pre;

          first = node;

         }else {

          node.next = pre.next ;

      pre.next = node;

     node.item = item;

         }

        

size++;

改变元素

  MyNode<E> result = first;

for(int i = 0;i<index;i++){

//遍历到当前的元素索引

result = result.next;

}

result.item = item;

得到元素

MyNode<E> result = first;

//遍历到当前的元素索引

for(int i = 0;i<index;i++){

result = result.next;

}

return result.item;

上述介绍的是单向链表,双向链表只不过比单向的多前驱和后继而已。

添加节点(相对于单向链表)

if (last != null) {

last.next = node;

node.pre = last;

}

删除节点

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> self = before.next;

result = self.item;

before.next = self.next;

self.next.pre = before;

self = null;

}

插入节点

if (index == 0) {

myNode.next = before;

before.pre = myNode;

first = myNode;

size++;

} else {

myNode.next = before.next;

before.pre = myNode;

before.next = myNode;

myNode.pre = before;

}

二叉树

 

树:是由n(n>=1)个有限节点组成一个具有层次关系的集合

树术语

节点度:一个节点含有子树的个数称为该节点的度

树的度:一棵树中,最大的节点的度为树的度

叶子节点:度为零的节点

父亲节点:若一个节点含有子节点,则当前节点为改子节点的父亲节点

子节点:一个节点含有子树,则子树的根节点为改节点的子节点

兄弟节点:具有相同父亲节点的子节点互为兄弟节点

节点层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推

树的深度(高度):树中节点最大的层次

其他:堂兄弟节点、子孙、森林

无序树:树中的节点次序是没有规律的

有序树:指树中同层结点从左到右有次序排列,这样的树称为有序树。

 1)二叉树:每个节点最多含有两个子树的树称为二叉树

 2)非二叉树:所有不是二叉树的树都属于非二叉树

二叉树还分为完全二叉树和满二叉树

满二叉树是二叉树的父节点都有左孩子和右孩子

完全二叉树是子节点呈左右左右排列

创建一棵树首先要构建森林

要在另一个类中创建左右节点还有树的值

TreeNode leftTree;

TreeNode rightTree;

int value;

构建森林

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).setLeftTree(list.get(2*i+1));

list.get(i).setRightTree(list.get(2*i+2));

}

//将最后一个节点单独处理

int lastIndex = list.size()/2-1;

list.get(lastIndex).setLeftTree(list.get(2*lastIndex+1));

//这里是判断是否为满二叉树

if(list.size()%2==1) {

list.get(lastIndex).setRightTree(list.get(2*lastIndex+2));

}

以上,一颗二叉树构建完毕

树的遍历

先序遍历树

 先访问根节点,然后访问左子树,最后访问右子树

将树作为参数传入方法中

public void beforeSearch(TreeNode tn) {

//根

System.out.println(tn.getValue());

//左

if(tn.getLeftTree()!=null) {

beforeSearch(tn.getLeftTree());

}

//右

if(tn.getRightTree()!=null) {

beforeSearch(tn.getRightTree());

}

}

中序遍历树

 先访问左子树,然后访问根节点,最后访问右子树

public void midSearch(TreeNode tn) {

//左

if(tn.getLeftTree()!=null) {

midSearch(tn.getLeftTree());

}

//根

System.out.println(tn.getValue());

//右

if(tn.getRightTree()!=null) {

midSearch(tn.getRightTree());

}

}

后续遍历树

 先访问左子树,然后访问右子树,最后访问根节点

public void lastSearch(TreeNode tn) {

//左

if(tn.getLeftTree()!=null) {

lastSearch(tn.getLeftTree());

}

//右

if(tn.getRightTree()!=null) {

lastSearch(tn.getRightTree());

}

//根

System.out.println(tn.getValue());

}

猜你喜欢

转载自blog.csdn.net/qq_37438795/article/details/78377854