List接口有序有索引,允许重复
list.add();//添加
list.remove(索引);//移除
list.set(索引,"");//替换
list集合遍历三种方式
for(int i=0;i<list.size();i++)
迭代器Iterator<String> it=list.Iterator();
while(it.hasNext){};
增强for循环for(String s:list){};
LinkedList底层是链表
LinkedList<String> linked=new LinkedList<>();//不能使用多态
linked.pop;//相对于list的remove
数组:查询快(首地址索引可以快速查找)增删慢(创建新数组,原数组垃圾回收)
//判断为空
public boolean isEmpty(){
return size==0;
}
//获取容量
public int getCapacity(){
return data.length;
}
//获取元素个数
public int getSize{
return size;
}
//添加一个元素
public void addLast(int e){
if(size==data.length)
throw new IllegalArgumentException(AddLast failed.Array is full)
data【size】=e;
size++;
}
//指定位置添加元素
public void add(int e,int index){
if(size==data.length)
throw new IllegalArgumentException(Add failed.Array is full)
if(index<0||index>size)
throw new IllegalArgumentException(Add failed.Require index>=0 and index <=size)
for(int i =size-1;i>=index; i--)
data[i] = data[i-1];
data[index] = e;
size++;
//字符串输出
public String toString(){
String string = new String();
string.append("[")
for(int i=0;i<size; i++){
string.append(i);
if(i!=size-1)
string.append("]");
}
return string.toString();
}
//搜索
public boolean contains(int e){
for(int i =0;i <size;i++){
if(data[i]=e)
return true;
}return false;
}
//删除
public int remove(int index){
if(index<0||index>size)
throw new IllegalArgumentException(Add failed.Require index>=0 and index <=size)
int a = data[index];
for(int i =index+1;i<size;i++)
data[i-1]=data[i];
size--;
return a;
}
栈
Stack<String> stack = new Stack<>();
//添加到栈顶
stack.push(e);
//删除栈底并返回该元素
stack.push(e);
队列
Queue<String> queue = new Queue<>();
//元素添加到队列尾
queue.enqueue(e);
//删除队列头
queue.dequeue(e);
循环队列
//队尾添加元素
public void enqueue(E e){
if(tail+1)%data.length == front;
resize(getCapacity * 2);
data[tail] = e;
tail = (tail+1)%data.length;
size++;
}
//队首删除元素
Public void dequeue(){
if(isEmpty()
throw new
E ret = data[front];
data[front] = null;
front = (front+1)% data.length;
return ret;
size--;
//扩容
private void resize(int new Capacity){
E[] newData = (E[])new Object[beCapacity+1];
for(int i = 0;i<size;i++)
newData[i] = data[front+i]%data.length;
data = newData;
front=0;
tail =size;}
//得到容积
public int getCapacity(){
return data.length-1;
}
队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。
使用java中的linkedList集合来实现一个队列,通过调用linkedList中的方法来实现队列的入队出队,判空等操作
Queue<Node> q = new LinkedList<>():
链表 是动态结构,不需要提前分配空间,,地址不连续,查询需从头开始,插入和删除不需要移动元素 (查询慢增删快)
一个元素也叫做一个节点,一个节点包括一个数据和两个地址
链表的增加删除修改查找O(n)
数据存储在节点Node中,优点是真正的动态不需要处理固定容量的问题,缺点是丧失随机访问能力
//头部插入新元素,头没有前面的节点
public void addFirst(E e){
Node node = new Node(e);
node.next = head;
head = node;
size++;
}
//设立虚拟节点
dummyhead
//尾部插入
public void addLast(E e){
Node node = new Node(e);
if(tail==null)
tail=head=node;
else{tail.next = node;
tail = tail.next;}
size++;
}
//指定位置插入元素
public void add(int index, E e){
if(index==0)
addFirst(e);
else if(index>size\\index<0)
throw
else{
Node pre = head;
for(int i = 0; i<index-1;i++)
pre = pre.next;
Node node = new Node(e);
node.next = pre.next;
pre.next = node;
size++;
}
}
//获得索引元素
public void get(int index,){
if(index<0 || index>=size)
throw
Node cur = head.next;
for(int i=0;i<index;i++)
cur = cur.next;
return cur;
//查询是否有e
public boolean find(int e){
Node cur = head.next;
while(cur!=null){
if(cur=e){
return true;
cur = cur.next;}
return false;
//更新
public void set(int index,int e){
if(index<0 || index>=size)
throw
Node cur = head.next;
for(int i=0;i<index;i++)
cur = cur.next;
cur = e;}
//删除
public E remove(int index){
if(index<0 || index>=size)
throw
Node pre = head;
for(int i =1;i<index;i++){
pre=pre.next;
Node restnode = pre.next;
pre.next = retnode.next;
retnode.next = null;}
return E retnode;
堆
堆:每个节点的值都大于等于其左右子节点的值称为大顶堆,arr[i]>=arr[2*i+1]&&arr[i]>=arr[2*i+2]
每个节点的值小于等于其左右子节点的值称为小顶堆
package day;
import java.util.Arrays;
public class HeapSort{
public static void main(String[] args){
int[] arr= {4,7,1,2,6};
heapSort(arr);
}
//编写一个堆排序的方法
public static void heapSort(int arr[]) {
int t=0;
for(int i=arr.length/2-1;i>=0;i--) {
adjustheap(arr, i, arr.length);}
for(int j=arr.length-1;j>=0;j--) {
t=arr[j];
arr[j]=arr[0];
arr[0]=t;
adjustheap(arr, 0,j);
}
System.out.println(Arrays.toString(arr));
}
/**
@param arr待调整数组
@param i 非叶子节点在数组中索引
@param length 对多少个元素继续调整
*/
//将数组调整成大顶堆
public static void adjustheap(int arr[],int i,int length) {
int t=arr[i];
//开始调整,i的左子节点是2*i+1
for(int k=2*i+1;k<length;k=k*2+1) {
//左子节点小于右子节点
if(arr[k+1]<arr[k+1]&&k+1<length) {
k++;//指向右子节点
}
if(arr[k]>t) {//如果子节点大于父节点
arr[i]=arr[k];//较大值赋给当前节点
i=k;//i指向k,继续循环比较
}else {
break;
}
}
arr[i]=t;//将原来的值放调整后的位置
}
}
package day;
public class ArrayBinaryTreedemo{
//顺序存储二叉树
public static void main(String[] args){
int[] arr= {1,2,3,4};
ArrayBinaryTree arrayBinaryTree=new ArrayBinaryTree(arr);
//arrayBinaryTree.preorder(0);
arrayBinaryTree.preorder();
}
class ArrayBinaryTree{
private int[] arr;
public ArrayBinaryTree(int[] arr) {
this.arr=arr;
}
//重载方法
public void preorder() {
this.preorder(0);
}
//编写一个方法完成前序遍历
public void preorder(int index) {
if(arr==null||arr.length==0) {
System.out.println("数组为空,不能进行前序遍历");
}//输出当前这个元素
System.out.println(arr[index]);
//左递归遍历
//第n个元素左子节点为2*n+1
if((index*2+1)<arr.length) {
preorder(2*index+1);
}
//右递归遍历
//第n个元素右子节点为2*n+2
if((index*2+2)<arr.length) {
preorder(2*index+2);
}
}
}}
遍历
package day;
public class BinaryTreedemo{
public static void main(String[] args){
BinaryTree binaryTree=new BinaryTree();
//创建节点
HerodNode root=new HerodNode(1, "Ruby");
HerodNode HerodNode1=new HerodNode(2, "Weiss");
HerodNode HerodNode2=new HerodNode(3, "Blake");
HerodNode HerodNode3=new HerodNode(4, "Yang");
//创建二叉树
root.setLeftHerodNode(HerodNode1);
root.setRightHerodNode(HerodNode2);
HerodNode2.setLeftHerodNode(HerodNode3);
binaryTree.setRoot(root);
//前序遍历
binaryTree.preorder();
//前序查找
HerodNode resHerodNode=binaryTree.preordersearch(1);
if(resHerodNode!=null) {
System.out.printf("no=%dname=%s,resHerodNode.getNo(),resHerodNode.getName()");
}else {
System.out.printf("没有找到");
}
}
//定义二叉树
class BinaryTree{
private HerodNode root;
public void preorder() {//前序遍历
if(this.root!=null) {
this.root.preorder();
}
System.out.println("二叉树空");
}
public void inorder() {
if(this.root!=null) {
this.root.preorder();
}
System.out.println("二叉树空");
}
public void postorder() {
if(this.root!=null) {
this.root.preorder();
}
System.out.println("二叉树空");
}
public HerodNode preordersearch(int no) {//前序查找
if(root!=null) {
return root.preordersearch(no);
}else {
return null;
}
}
public void del(int no) {
//是空树则等价二叉树置空
if(this.root!=null) {
//判断root是不是要删除的节点
if(root.getNo()==no) {
this.root=null;}else {
root.del(no);
}
}
else {System.out.println("空树不能删除");
}
}
}
//创建HerodNode节点
class HerodNode{
private int no;
private String name;
private HerodNode leftHerodNode;//默认null
private HerodNode rightHerodNode;//默认null
public HerodNode(int no, String nameString) {
super();
this.no = no;
this.name = nameString;
}//private的只有对象自己才可以访问,安全性高,其他对象只能通过它的public方法,
//set,get来获取或设置原对象的private属性。而public其他对象可以访问,安全性就不高了。
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public HerodNode getLeftHerodNode() {
return leftHerodNode;
}
public void setLeftHerodNode(HerodNode leftHerodNode) {
this.leftHerodNode = leftHerodNode;
}
public HerodNode getRightHerodNode() {
return rightHerodNode;
}
public void setRightHerodNode(HerodNode rightHerodNode) {
this.rightHerodNode = rightHerodNode;
}//toString()将节点更方便输出
@Override
public String toString() {
return "HerodNode [no=" + no + ", name=" + name + "]";
}
//前序遍历
public void preorder() {
System.out.println(this);//输出父节点
//不为空递归左子树
if(this.leftHerodNode!=null) {
this.leftHerodNode.preorder();
}
//递归右子树
if(this.rightHerodNode!=null) {
this.rightHerodNode.preorder();
}
}
//中序遍历
public void inorder() {
//不为空递归左子树
if(this.leftHerodNode!=null) {
this.leftHerodNode.preorder();
}
System.out.println(this);//输出父节点
//递归右子树
if(this.rightHerodNode!=null) {
this.rightHerodNode.preorder();
}
}
//后序遍历
public void postorder() {
//不为空递归左子树
if(this.leftHerodNode!=null) {
this.leftHerodNode.preorder();
}
//递归右子树
if(this.rightHerodNode!=null) {
this.rightHerodNode.preorder();
}
System.out.println(this);//输出父节点
}
//前序查找,找到就返回Node没找到就null
public HerodNode preordersearch(int no) {
//比较当前节点
if(this.no==no) {
return this;//谁调用this,this就指向谁
}
//判断左子节点是否为空,不为空就递归前序查找,找到节点则返回
HerodNode resHerodNode=null;
if(this.leftHerodNode!=null) {
resHerodNode=this.leftHerodNode.preordersearch(no);
}
if(resHerodNode!=null) {//已找到
return resHerodNode;
}
//判断右子节点是否为空,不为空就递归前序查找
if(this.rightHerodNode!=null) {
resHerodNode=this.rightHerodNode.preordersearch(no);
}
return resHerodNode;
}
//二叉树是单向的,所以判断当前节点的子节点是否需要删除,而不是判断当前这个节点是不是需要删除
public HerodNode del(int no) {
//如果左子节点不为空,且左子节点就是要删除节点,this.left=null然后返回
if(this.leftHerodNode==no&&this.leftHerodNode!=null) {
this.leftHerodNode=null;
return;
}
//如果右子节点不为空,且左子节点就是要删除节点,this.right=null然后返回
if(this.rightHerodNode==no&&this.rightHerodNode!=null) {
this.rightHerodNode=null;
return;
}
//如果左右子节点不是要删除的,就向左子树,递归删除
if(this.leftHerodNode!=null) {
this.leftHerodNode(no);
}
//如果左子树没有就向右子树,递归删除
if(this.rightHerodNode!=null) {
this.rightHerodNode(no);
}
}
}
}
集合set
Set:1.不允许重复对象
2. 无序容器,没有索引,无法for循环,底层是哈希表(查询速度快)
3. 只允许一个 null 元素
4.Set 接口最流行的几个实现类是 HashSet、LinkedHashSet 以及 TreeSet。最流行的是基于 HashMap 实现的 HashSet;TreeSet 还实现了 SortedSet 接口,因此 TreeSet 是一个根据其 compare() 和 compareTo() 的定义进行排序的有序容器。
Set<Integer> set= new HashSet<>();
set.add();//添加
Iterator<Integer> it=set.iterator();
while(it.hasNext()){
Integer n=it.next();
}
HashSet
哈希值是一个十进制整数由系统随机给出,是一个模拟出的逻辑地址int hashCode()返回哈希值是object类的方法
HashSet中的键值是唯一的,不可重复的
HashSet<String> set = new HashSet<>();
String s1 = new String("aaa");
set.add(s1);
HashSet存储自定义类型元素需要重写hashcode方法和equals方法
映射Map
多重映射key可以重复
映射基于二分搜索树实现,二分搜索树元素必须comparable
public class BSTMap<K extends Comparable<K>,V> implements Map<K,V>{
private class Node{
public K key;
public V value;
public Node left,right;
public Node(K key,Vvalue){
this.key = key;//this.key即用户传来的key
this.value = value;
left = null;
right = null;}}
private Node root;
private int size;
public BSTMap(){
root = null;
size=0;}
public int getSize(){
return size;}
public boolean isEmpty(){
return size==0;}
//向以node为根的二分搜索树中插入元素(key,value),递归算法
//返回插入新节点后二分搜索树的根
public void add(K key, V value)
root = add(root,key,value);
private Node add(Node node, K key, V value){
if(node == null){
size ++;
return new Node(key,value):}
if(key.compareTo(node.key)<0)
node.left = add(node.left,key,value);
else if(key.compareTo(node.key)>0)
node.right = add(node.right,key,value);
else
node.value = value;
return node;}
//返回以node为根节点的二分搜索树key所在的节点
private Node getNode(Node node,K key){
if(node==null)
return null;
if(key.comparaTo(node.key)==0)
return node;
else if(key.comparaTo(node.key)<0)
return getNode(node.left,key);
else
return getNode(node.right,key);
//得到key所对应的value
public V get(K key){
Node node = getNode(root,key);
return node==null?null:node.value;}
//删除掉以node为根的二分搜索树中值为e的节点,递归算法
//返回删除节点后新的二分搜索树的根
public void remove(K key){
Node node = getNode(root);
if(node!=null){
roote = remove(root,e);
return node.value;}
return null;}
private Node remove(Node node,K key){
if(node==null)
return null;
if(key.compareTo(node.key)<0)
{node.left = remove(node.left,key);
return node;}
else if(key.compareTo(node.key)>0)
{node.right = remove(node.right,key);
return node;}
else{//待删除节点左子树为空
if(node.left==null){
Node rightnode = node.right;
node.right = null;
size--;
return rightnNode;}
if(node.right==null){
Node leftnode = nodeleft;
node.left = null;
size--;
return leftnNode;}
`//带删除节点左右子树都不空,找到比待删除节点大的最小节点,即待删除节点右子树最小节点
Node successor = minimum(node.right);
succeor.rgh remove(node.rght);
uccessor.left = node.lef;
node.left= node.right=null;
可变参数(类型确定,个数不确定,底层是数组)