一、栈
- 栈是一种线性结构
- 栈是操作受限的数组,只能从一端添加数据和删除数据
- 栈是一种后进先出的数据结构。last in first out lifo
栈的应用
- 无处不在的Undo操作(撤销)
- 程序调用的系统栈。可以记录一个程序上次终止运行的位置,进栈,进而下次知道从哪里开始执行
- 括号匹配-编译器
二、队列
- 队列queue是一种线性结构
- 队列是操作受限的数组,只能从一端添加元素(队尾),从另一端删除元素(队头)
- 先进先出。first in first out FIFO
循环队列
三、链表
优点:真正的动态,不需要考虑容量问题
缺点:丧失了随机访问的能力
/**总结一哈
* 1.在有虚拟头结点的链表中,dummyHead虚拟头结点默认指向索引0之前
* 1.获取索引index之前的元素prev
* Node prev = dummyHead;
* for (int i=0;i<index;i++)
* prev=prev.next;
* 2.获取索引index当前的元素current
* Node current = dummyHead.next;
* for (int i=0;i<index;i++)
* current=current.next;
* 2.只要方法中有索引index,一定要先判断合法性
* 3.增删链表之后,不要忘记操作size
*/
public class LinkedList<E> {
/**
* 结点类
*/
private class Node{
public E e;
public Node next;
public Node(E e, Node next) {
this.e = e;
this.next = next;
}
public Node() {
this(null,null);
}
public Node(E e){
this(e,null);
}
@Override
public String toString() {
return e.toString();
}
}
//private Node head;
//虚拟头结点
private Node dummyHead;
private int size;
public LinkedList() {
dummyHead=new Node(null, null);
size=0;
}
//获取链表个数
public int getSize(){
return size;
}
//链表是否为空
public boolean isEmpty(){
return size==0;
}
//在链表头添加数据e
public void addFirst(E e){
add(0, e);
size++;
}
//在链表任意索引位置添加元素
public void add(int index,E e){
//判断索引合法性
if(index<0||index>size)
throw new IllegalArgumentException("index error");
//prev是索引x的前一个元素,默认指向虚拟头结点,而dummyHead在索引0之前,prev.next执行1次为索引1之前,则遍历index次为索引index之前
Node prev = dummyHead;
for (int i=0;i<index;i++)
prev=prev.next;
// Node node = new Node(e);
// node.next=prev.next;
// prev.next=node;
prev.next=new Node(e,prev.next);
size++;
}
//在链表末尾添加元素
public void addLast(E e){
add(size, e);
}
//获得某个索引处的元素
public E get(int index){
//判断索引合法性
if(index<0||index>=size)
throw new IllegalArgumentException("index error");
Node current = dummyHead.next;
for (int i=0;i<index;i++)
current=current.next;
return current.e;
}
//获取第一个元素
public E getFirst(){
return get(0);
}
//获取最后一个元素
public E getLast(){
return get(size-1);
}
//修改指定索引元素
public void set(int index,E e){
//判断索引合法性
if(index<0||index>=size)
throw new IllegalArgumentException("index error");
//获取index位置元素
Node current=dummyHead.next;
for (int i=0;i<index;i++)
current=current.next;
current.e=e;
}
//判断是否含有某个元素
public boolean contains(E e){
Node cur=dummyHead.next;
while(cur!=null){
if (cur.e.equals(e))
return true;
cur=cur.next;
}
return false;
}
//遍历
@Override
public String toString(){
Node cur=dummyHead.next;
StringBuilder sb = new StringBuilder();
while(cur!=null){
sb.append(cur+"->");
cur=cur.next;
}
sb.append("null");
return sb.toString();
}
//删除某个位置的元素
public E remove(int index){
//判断索引合法性
if(index<0||index>=size)
throw new IllegalArgumentException("index error");
Node prev=dummyHead;
for (int i=0;i<index;i++)
prev=prev.next;
Node delNode=prev.next;
prev.next=delNode.next;
delNode.next=null;
size--;
return delNode.e;
}
public E removeFirst(){
return remove(0);
}
public E removeLast(){
return remove(size-1);
}
}
四、递归
- 链表具有天然的递归结构
- 二叉树具有天然的递归结构
- 每个节点的左子树也是二叉树
- 每个节点的右子树也是二叉树
五、树
二叉树
-
二叉树不一定是满的
- 一个节点也是二叉树,只不过左右节点都为空
- NULL 空也是二叉树
-
对于满二叉树,如果有h层,则共有有2^h-1个节点
二分搜索树
BST Binary search tree
- 二分搜索树是二叉树
- 二分搜索树每个节点的值
- 大于其左子树的所有节点的值
- 小于其右子树的所有节点的值
- 每一棵子树也是二分搜索树
- 存储的元素必须有可比较性
//二分搜索树要通过比较节点与节点的大小,以此来判断相对位置
//不是基本类型就不能使用<、>、=进行比较,类型E继承Comparable<E>,实现具有可比性
public class BST<E extends Comparable<E>> {
private class Node{
public E e;
public Node left,right;
public Node(E e){
this.e=e;
left=null;
right=null;
}
}
private Node root;
private int size;
public BST(){
root=null;
size=0;
}
}
1. 插入元素_递归
/*
//向二分搜索树中插入元素
public void add(E e){
if(root==null){
root=new Node(e);
size++;
}
else
add(root,e);
}
//向以node为根的二叉树中插入元素e,递归算法
private void add(Node node,E e){
//递归终止条件
if (e.equals(node.e))
return;
if (e.compareTo(node.e)<0&&node.left==null)
node.left=new Node(e);
if (e.compareTo(node.e)>0&&node.right==null)
node.right=new Node(e);
if (e.compareTo(node.e)<0)
add(node.left,e);
else
add(node.right,e);
}
*/
//对上述递归方法的优化
//向二分搜索树中插入元素
public void add(E e){
root