二叉树、栈、队列、链表的Java代码实现

时间:2022-09-06 20:22:21

这是我的学习总结。
如有文章存在谬误,欢迎指出,有其他意见或者建议,也欢迎留言

二叉树链表

前序遍历:先访问根节点,然后访问左子树、右子树
中序遍历:先访问左子树,然后访问根节点、右子树
后序遍历:先访问左子树、右子树,然后访问根节点

二叉树

/**
* 二叉树
*
* @author ChenSS 2016/11/10
* @version 1.0
*/
public class BinaryTree {
// 根节点数据
int data;
// 左子树
BinaryTree left;
// 右子树
BinaryTree right; public BinaryTree(int data) {
this.data = data;
left = null;
right = null;
} /**
* 插入新的节点,以根节点为准,大的放右边,小的放左边
*
* @param root
* 根节点
* @param data
* 数据
*/
public void insert(BinaryTree root, int data) {
if (data > root.data) {
if (root.right == null) {
root.right = new BinaryTree(data);
} else {
this.insert(root.right, data);
}
} else {
if (root.left == null) {
root.left = new BinaryTree(data);
} else {
this.insert(root.left, data);
}
}
}
}

二叉树遍历:

/**
* 二叉树遍历
*
* @author ChenSS 2016/11/10
* @version 1.0
*/
public class BinaryTreePreorder {
/**
* 先根遍历,优先输出根节点的值,然后遍历左子树,左子树为空,就遍历右子树
* 假设左子树不为空,输出左子树的根节点,继续对左子树的左右子树相同判断
*/
public static void preOrder(BinaryTree root) {
if (root == null)
return;
System.out.print(root.data + "-");
preOrder(root.left);
preOrder(root.right);
} /**
* 中根遍历
*/
public static void inOrder(BinaryTree root) {
if (root == null)
return;
inOrder(root.left);
System.out.print(root.data + "-");
inOrder(root.right);
} /**
* 后根遍历
*/
public static void postOrder(BinaryTree root) {
if (root == null)
return;
postOrder(root.left);
postOrder(root.right);
System.out.print(root.data + "-");
} public static void main(String[] str) {
int[] array = { 12, 76, 35, 22, 16, 48, 90, 46, 9, 40 };
BinaryTree root = new BinaryTree(array[0]);
for (int i = 1; i < array.length; i++) {
root.insert(root, array[i]); // 向二叉树中插入数据
}
System.out.println("先根遍历:");
preOrder(root);
System.out.println();
System.out.println("中根遍历:");
inOrder(root);
System.out.println();
System.out.println("后根遍历:");
postOrder(root);
}
}

二叉树、栈、队列、链表的Java代码实现

生成的二叉树如上,先序遍历的输出情况为:
12-9-76-35-22-16-48-46-40-90
如图:
1. 第一个根节点是12,打印12.
2. 12有左子树和右子树,先遍历左子树,左子树根节点是9,打印9.
3. 9没有子树,所以会去判断12的右子树,右子树的根节点是76,打印76.
4. 76左右子树都有,先遍历左子树,左子树的根节点是35,打印35.
打印22……
打印16……
5. 35的左子树遍历完了,遍历右子树,打印48……

栈(Stack)是限制仅在表的一端进行插入和删除运算的线性表,是一种后进先出(LILO)的线性表。
二叉树、栈、队列、链表的Java代码实现

栈的链表实现

/**
* 链表栈
*
* @author ChenSS 2016/11/10
* @version 1.0
*/
public class LinkedStack implements AbsStack {
private int count;
private Node top; @Override
public void push(Object element) {
Node node = new Node(element);
node.setNext(top);
top = node;
count++;
} @Override
public Object pop() {
if (isEmpty())
throw new NullPointerException("stack is null");
Object result = top.getElement();
top = top.getNext();
count--;
return result;
} @Override
public boolean isEmpty() {
return size() == 0;
} @Override
public int size() {
return count;
} @Override
public Object peek() {
Object result = top.getElement();
return result;
} /**
* 链表,每一个对象拥有下一个对象的引用
*
* @author ChenSS
*
*/
private class Node {
// 链表元素
private Object element;
// 指向下一个元素的指针(引用)
private Node next; public Node(Object element) {
this.element = element;
} public void setNext(Node top) {
this.next = top;
} public Node getNext() {
return next;
} public Object getElement() {
return element;
}
} public static void main(String[] args) {
LinkedStack stack = new LinkedStack();
// 压栈10次
for (int i = 0; i < 10; i++) {
stack.push(i);
}
// 出栈5次
System.out.println("连续执行5次出栈操作");
for (int i = 0; i < 5; i++) {
System.out.println(stack.pop());
}
System.out.println("栈是否为空: " + stack.isEmpty());
System.out.println("栈的大小为: " + stack.size());
System.out.println("栈顶元素为: " + stack.peek());
}
}

栈的数组实现

/**
* 数组栈
*
* @author ChenSS 2016/11/10
* @version 1.0
*/
public class ArrayStack implements AbsStack {
// 初始化一部分空间
private Object[] objs = new Object[16];
private int size = 0; public void clear() {
for (int i = 0; i < size; i++)
objs[size] = null;
size = 0;
} @Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("ArrayStack: [");
for (int i = 0; i < size; i++) {
sb.append(objs[i].toString());
if (i != size - 1) {
sb.append(", ");
}
}
sb.append("]");
return sb.toString();
} @Override
public void push(Object element) {
if (size >= objs.length) {
resize();
}
objs[size++] = element;
} @Override
public Object pop() {
if (size == 0) {
return null;
}
return objs[--size];
} @Override
public Object peek() {
return objs[size];
} @Override
public boolean isEmpty() {
return size == 0;
} @Override
public int size() {
return size;
} /**
* 数组扩容,一次加5个
*/
private void resize() {
objs = Arrays.copyOf(objs, objs.length + 5);
} public static void main(String[] args) {
ArrayStack stack = new ArrayStack();
// 压栈10次
for (int i = 0; i < 10; i++) {
stack.push(i);
}
// 出栈5次
System.out.println("连续执行5次出栈操作");
for (int i = 0; i < 5; i++) {
System.out.println(stack.pop());
}
System.out.println("栈是否为空: " + stack.isEmpty());
System.out.println("栈的大小为: " + stack.size());
System.out.println("栈顶元素为: " + stack.peek());
System.out.println("元素为: " + stack.toString());
}
}

队列

队尾入列队头出,采用的是一种先进先出(LILO)的方式进行数据处理
二叉树、栈、队列、链表的Java代码实现

/**
* 队列
*
* @author ChenSS 2016/11/10
* @version 1.0
*/
public class Queue {
// 队列长度,由构造函数初始化
private int maxSize;
// 队列
private long[] queArray;
// 队头
private int front;
// 队尾
private int rear;
// 元素的个数
private int size; public Queue(int s) {
maxSize = s;
queArray = new long[maxSize];
front = 0;
rear = -1;
size = 0;
} // 进队列
public void add(long j) {
// 处理循环
if (rear == maxSize - 1)
rear = -1;
// 队尾指针加1,把值j加入队尾
queArray[++rear] = j;
size++;
} // 取得队列的队头元素。
public long take() {
// 取值和修改队头指针
long temp = queArray[front++];
// 处理循环
if (front == maxSize)
front = 0;
size--;
return temp;
} // 取得队列的队头元素。该运算与 remove()不同,后者要修改队头元素指针。
public long peek() {
return queArray[front];
} public boolean isEmpty() {
return (size == 0);
} // 判队列是否已满。若已满返回一个真值,否则返回一个假值。
public boolean isFull() {
return (size == maxSize);
} // 返回队列的长度
public int size() {
return size;
} public static void main(String[] args) {
// 队列有5个元素
Queue theQueue = new Queue(5); // 添加4个元素
theQueue.add(10);
theQueue.add(20);
theQueue.add(30);
theQueue.add(40); // 移除3个元素
theQueue.take();
theQueue.take();
theQueue.take(); // 添加4个元素
theQueue.add(50);
theQueue.add(60);
theQueue.add(70);
theQueue.add(80); // 遍历队列并移除所有元素
while (!theQueue.isEmpty()) {
long n = theQueue.take();
System.out.print(n);
System.out.print(" ");
}
}
}

链表

单向链表

在表头插入一个新的链接点,每个元素有下一个元素的指针(索引),根据当前元素,可以获取下一个元素。
二叉树、栈、队列、链表的Java代码实现

双端链表

与单向链表的不同之处在保存有对最后一个链接点的引用(last),实现了在链尾也可以插入数据的功能
二叉树、栈、队列、链表的Java代码实现

双向链表

在过去的学习中,我们使用到了迭代器,迭代器有个向后遍历的功能,而双向链表,就增加了一个功能:往回遍历。每一个元素有两个指针,一个指向前一个元素,一个指向后一个元素。(参考:LinkedList对象)
二叉树、栈、队列、链表的Java代码实现

LinkedList底层代码(LinkedList的元素):
每一个元素包含两个指针(引用),一个指向前面一个元素,一个指向后面一个元素,也就是说,我们只要能得到其中任何一个元素,就可以遍历整个链表。

   private static class Node<E> {
E item;
Node<E> next;
Node<E> prev; Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}

LinkedList逆向遍历功能展示:

/**
* LinkedList测试
*
* @author ChenSS 2016/11/10
* @version 1.0
*/
public class BinaryTreePlus {
public static void main(String[] args) {
LinkedList<String> list=new LinkedList<>();
list.addFirst("AAA");
list.addLast("BBB");
ListIterator<String> iterator=list.listIterator(list.size());
while(iterator.hasPrevious()){
System.out.println(iterator.previous());
}
}
}

LinkedList代码实现:

/**
* 双向链表
*
* @author ChenSS 2016/11/10
* @version 1.0
*/
public class DoubleLists<T> {
private DNode<T> header;
private int listSize; public DoubleLists() {
header = new DNode<T>();
listSize = 0;
}
private static class DNode<T> {
T nodeValue;
DNode<T> prev;
DNode<T> next; public DNode() { // for header
nodeValue = null;
prev = this; // left
next = this; // right
} public DNode(T item) {
nodeValue = item;
prev = this;
next = this;
}
} public boolean isEmpty() {
return (header.prev == header || header.next == header);
} public int size() {
return listSize;
} private DNode<T> addBefore(DNode<T> curr, T item) {
DNode<T> newNode, prevNode; newNode = new DNode<T>(item); prevNode = curr.prev; newNode.prev = prevNode;
newNode.next = curr; prevNode.next = newNode;
curr.prev = newNode; return newNode;
} public boolean add(T item) {
addBefore(header, item);
listSize++;
return true;
} public void addFirst(T item) {
addBefore(header.next, item);
listSize++;
} public void addLast(T item) {
addBefore(header, item);
listSize++;
} private void remove(DNode<T> curr) {
if (curr.next == curr)
return; DNode<T> prevNode = curr.prev, nextNode = curr.next; prevNode.next = nextNode;
nextNode.prev = prevNode;
} public boolean remove(Object o) {
for (DNode<T> p = header.next; p != header; p = p.next) {
if (o.equals(p.nodeValue)) {
remove(p);
listSize--;
return true;
}
}
return false;
} public void printList() {
for (DNode<T> p = header.next; p != header; p = p.next)
System.out.println(p.nodeValue);
} private class MyIterator implements Iterator<T> { public DNode<T> nextNode = header.next;
public DNode<T> lastReturned = header; public boolean hasNext() {
return nextNode != header;
} public T next() {
if (nextNode == header)
throw new NoSuchElementException(""); lastReturned = nextNode;
nextNode = nextNode.next;
return lastReturned.nodeValue;
} public void remove() {
if (lastReturned == header)
throw new IllegalStateException(""); DoubleLists.this.remove(lastReturned);
lastReturned = header;
listSize--;
}
} private class MyListIterator extends MyIterator implements ListIterator<T> { private int nextIndex; MyListIterator(int index) {
if (index < 0 || index > listSize)
throw new IndexOutOfBoundsException("");
if (index < (listSize >> 1)) {
nextNode = header.next;
for (nextIndex = 0; nextIndex < index; nextIndex++)
nextNode = nextNode.next;
} else {
nextNode = header;
for (nextIndex = listSize; nextIndex > index; nextIndex--)
nextNode = nextNode.prev;
}
} public boolean hasPrevious() {
return nextIndex != 0;
// return nextNode.prev != header;
} public T previous() {
if (nextIndex == 0)
throw new NoSuchElementException("no"); lastReturned = nextNode = nextNode.prev;
nextIndex--;
return lastReturned.nodeValue;
} public void remove() {
if (lastReturned == header)
throw new IllegalStateException(""); DoubleLists.this.remove(lastReturned);
nextIndex--;
listSize--; if (lastReturned == nextNode)
nextNode = nextNode.next;
lastReturned = header;
} public void add(T item) {
DoubleLists.this.addBefore(nextNode, item);
nextIndex++;
listSize++;
lastReturned = header;
} public void set(T item) {
if (lastReturned == header)
throw new IllegalStateException(); lastReturned.nodeValue = item;
} public int nextIndex() {
return nextIndex;
} public int previousIndex() {
return nextIndex - 1;
}
} public Iterator<T> iterator() {
return new MyIterator();
} public ListIterator<T> listIterator(int index) {
return new MyListIterator(index);
} public static void main(String[] args) {
DoubleLists<String> t = new DoubleLists<String>();
t.add("A");
t.add("B");
t.remove("B");
t.addFirst("AA");
t.addLast("BB");
t.add("C");
t.add("D"); ListIterator<String> it = t.listIterator(t.size()); while (it.hasPrevious()) {
//指向位置前面的元素
System.out.println(it.previous());
}
}
}

4种常见的排序

/**
* 排序算法
*
* @author ChenSS 2016/11/10
* @version 1.0
*/
public class SortUtil {
/**
* 选择排序,采用记角标的方式,记住数组中最小的那个数的角标,然后与开始的元素交换位置
*/
public static void selectSort(int[] a) {
int index;
int temp;
for (int i = 0; i < a.length - 1; i++) {
index = i;
for (int j = i + 1; j < a.length; j++) {
if (a[index] > a[j])
index = j;
}
if (index != i) {
temp = a[index];
a[index] = a[i];
a[i] = temp;
}
} } /**
* 快速排序,以一个数为基准(通常选第一个数),大数置于右边,小数置于左边,
* 此后以相同的算法对左边和右边这两组数进行排序,以此类推,
* 直至整个数组从小到大排列
*/
public static void quickSort(int[] a, int left, int right) {
if (left >= right)
return;
int temp = a[left];
int low = left;
int high = right;
while (low < high) {
while (low < high && a[high] >= temp)
high--;
a[low] = a[high];
while (low < high && a[low] <= temp)
low++;
a[high] = a[low];
}
a[low] = temp;
quickSort(a, left, low - 1);
quickSort(a, low + 1, right);
} /**
* 冒泡排序
*/
public static void bubbleSort(int[] a) {
int temp;
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a.length - i - 1; j++) {
if (a[j] > a[j + 1]) {
temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
}
}
}
} /**
* 插入排序,和选择排序类似,遍历取出最小的那个数,然后插入到第一个元素的位置,其它元素全部后移
*/
public static void insertSort(int a[]) {
for (int i = 1; i < a.length; i++) {
int key = a[i];
int index = i;
while (index > 0 && a[index - 1] > key) {
a[index] = a[index - 1];
index--;
}
a[index] = key;
}
} /**
* 测试方法
*/
public static void print(int a[]) {
for (int i = 0; i < a.length; i++) {
System.out.print(a[i] + " ");
}
System.out.println();
} public static void main(String[] args) {
int[] arr = { 7, 6, 5, 4, 2, 3, 9, 90, 4, 50 };
insertSort(arr);
print(arr);
}
}

二叉树、栈、队列、链表的Java代码实现的更多相关文章

  1. 单链表反转java代码

    据说单链表反转问题面试中经常问,而链表这个东西相对于数组的确稍微难想象,因此今天纪录一下单链表反转的代码. 1,先定义一个节点类. public class Node { int index; Nod ...

  2. 二叉树的层次遍历(Java代码实现)

    与树的前中后序遍历的DFS思想不同,层次遍历用到的是BFS思想.一般DFS用递归去实现(也可以用栈实现),BFS需要用队列去实现. 层次遍历的步骤是: 1.对于不为空的结点,先把该结点加入到队列中 2 ...

  3. 4、链栈的实现(java代码)

    1.链节点 public class Node<T> { public T data; public Node next; } 2.实现代码 public class Stack<T ...

  4. java代码实现队列的优化

    package com.voole.queun; /** * @Decription 队列 * @author TMAC-J * */ public class Queun { /** * 初始化队列 ...

  5. 数据结构之链表及其Java实现

    数据的存储一般分线性存储结构和链式存储结构两种.前者是一种顺序的存储方式,在内存中用一块连续的内存空间存储数据,即逻辑上相连的物理位置相邻,比较常见的就是数组:后者是一种链式存储方式,不保证顺序性,逻 ...

  6. java面向对象的栈 队列 优先级队列的比较

    栈 队列 有序队列数据结构的生命周期比那些数据库类型的结构(比如链表,树)要短得多.在程序操作执行期间他们才被创建,通常用他们去执行某项特殊的任务:当完成任务之后,他们就会被销毁.这三个数据结构还有一 ...

  7. java 集合 Connection 栈 队列 及一些常用

    集合家族图 ---|Collection: 单列集合 ---|List: 有存储顺序 , 可重复 ---|ArrayList: 数组实现 , 查找快 , 增删慢 ---|LinkedList: 链表实 ...

  8. Java 容器之 Connection栈队列及一些常用

    集合家族图 ---|Collection: 单列集合 ---|List: 有存储顺序 , 可重复 ---|ArrayList: 数组实现 , 查找快 , 增删慢 ---|LinkedList: 链表实 ...

  9. java 栈和队列的模拟--java

    栈的定义:栈是一种特殊的表这种表只在表头进行插入和删除操作.因此,表头对于栈来说具有特殊的意义,称为栈顶.相应地,表尾称为栈底.不含任何元素的栈称为空栈. 栈的逻辑结构:假设一个栈S中的元素为an,a ...

随机推荐

  1. Snap&period;svg – 现代 Web 开发必备的 JavaScript SVG 库

    SVG 是一种很好的 Web 技术方案,可以用来创建互动,在任何大小的屏幕上都会很好看.与分辨率无关的矢量图形.而这里推荐的 Snap.svg 这个 JavaScript 可以让你像 jQuery 操 ...

  2. Linux 的 strace 命令

    https://linux.cn/article-3935-1.html http://www.cnblogs.com/ggjucheng/archive/2012/01/08/2316692.htm ...

  3. CentOS 6&period;5下利用Rsyslog&plus;LogAnalyzer&plus;MySQL部署日志服务器

    一.简介 LogAnalyzer 是一款syslog日志和其他网络事件数据的Web前端.它提供了对日志的简单浏览.搜索.基本分析和一些图表报告的功能.数据可以从数据库或一般的syslog文本文件中获取 ...

  4. TeX Live安装配置等默认目录

    TeX Live默认目录情况:   TEXDIR (the main TeX directory):     !! default location: /usr/local/texlive/2015  ...

  5. Windows 2008R2关闭网络发现

    在Windows Server 2008 R2安装完后,默认情况下,在高级共享设置中无法对网络发现的更改进行保存(每次选择"启用网络发现"后保存修改,但重新打开"高级共享 ...

  6. HTML CSS &plus; DIV实现局部布局

    HTML CSS + DIV实现局部布局 HTML CSS + DIV实现局部布局 1.本章教大家掌握2种布局方式: 1)顶部导航菜单布局,效果图: 2)购物版块布局,效果图: 2.技术目标: 使用d ...

  7. &lbrack;Everyday Mathematics&rsqb;20150120

    设 $f:\bbR\to\bbR$ 二阶可微, 且 $$\bex f(0)=2,\quad f'(0)=-2,\quad f(1)=1. \eex$$ 试证: $$\bex \exists\ \xi\ ...

  8. 通过linux版本的lr agent提示找不到web&lowbar;reg&lowbar;save&lowbar;param&lowbar;ex函数

    Action.c(5): Error: C interpreter run time error: /tmp/brr_TSBgR2/netdir/E/lrscript/aaa/Action.c (5) ...

  9. 设计模式のProxyPattern(代理模式)----结构模式

    一.产生背景 在直接访问对象时带来的问题,比如说:要访问的对象在远程的机器上.在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会 ...

  10. 黄聪:通过 itms&colon;services&colon;&sol;&sol;&quest; 在线安装ipa ,跨过appstore

    1.需要一个html文件,引导下载用户在线安装ipa <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN&quo ...