Java 数据结构 笔记

199 阅读8分钟

数据结构

物理结构

顺序储存结构

使用连续的内存单位依次存放数据元素,物理存储次序与他们的逻辑次序相同

实现

数组

链式储存结构

使用地址分散的储存单元储存数据,逻辑结构由附加信息指定

实现

使用指针表示数据的逻辑结构

逻辑结构

  • 线性表

线性结构

具有线性关系的数据结构

特点

  • ai只有一个前驱和一个后继,a0没有前驱,an没有后继

  • 可以根据序号确定数据元素在线性结构中的逻辑次序

实现

抽象抽象数据类型

ADT List<T>{
	boolean isEmpty()
    int size()
    T get(int i)
    void set(int i,T x)
    String toString()
    int insert(T x,int i)
    int insert(T x)
    T remove(int i)
    void clear()    
    int search(T x)
    boolean contains(T key)
    int insertDifferent(T x)
    T remove(T x)
    boolean equals(Object obj)
    void addAll(List<T> lsit)    
}
顺序储存结构
public class SeqList<T>{
	protected Object[] element;
    private int n;
    public SeqList(int length){
        if(length>=0){
         	this.element = new Object[length];
        	this.n = 0;   
        }else{
            throw new IllegalArgumentsException("表长不能未负");
        }
    }
    public SeqList(){
        this(64);
    }
    public SeqList(T[] values){
        this(values.length);
        for(int i=0;i<values.length;i++){
            this.element[i] = values[i];
        }
        this.n = values.length;
    }
    public boolean isEmpty(){
        return this.n==0;
    }
    public int size(){
        return this.n;
    }
    public T get(int i){
        if(i>=0){
        	return this.element[i];
        }else{
            throw new IllegalArgumentsException("下标不能为负");
        }
    }
    public void set(int i,T x){
        this.element[i] = x;
    }
    public String toString(){
         
    }
    
}
数组

储存相同类型数据元素的集合

储存空间连续

无法进行插入、删除操作

复杂度

空间:O(n)

时间:O(n)

链式储存结构
public Node<T>{
    public T date;
    public Node<T> next;
    public Node(T data,Node<T> next){
        this.data = data;
        this.next = next;
    }
    public Node(){
        this(null,null);
    }
    public String toString(){
        return this.data.toString();
    }
}

栈和队列

只允许在一段进行插入和删除操作的线性表

栈顶:允许操作

栈底:不允许操作

特点:

后进先出(LIFO)

实现
public interface Stack<T>{
    public abstract boolean isEmpty();
    public abstract void push(T x);
    public abstract T peek();
    public abstract T pop();
}
顺序储存结构
public final class SeqStack<T>{
    private SeqList<T> list;
    public SeqStack(int length){
        this.list = new Seqlist<T>(length);
    }
    public SeqStack(){
        this(64);
    }
    public boolean isEmpty(){
        return this.list.isEmpty();
    }
    public void push(T x){
        this.list.insert(x);
    }
    public T peek(){
        return this.list.get(this.list.size()-1);
    }
    public T pop(){
        return this.list.remove(this.list.size()-1);
    }
}
链式储存结构
public final class LinkedStack<T> impelements Stack<T>{
    private SinglyList<T> list;
    public LinkedStack(){
        this.list = new SinglyList<T>();
    }
    public boolean isEmpty(){
    	return this.list.isEmpty();
    }
    public void push(T x){
        this.list.insert(0,x);
    }
    public T peek(){
        return this.list.get(0);
    }
    public T pop(){
        return this.list.remove(0);
    }
}
应用
  1. 嵌套调用的实现基础
  2. 以非递归方式实现递归算法

队列

删除,插入分别在两端的线性表

特点:

先进先出(FIFO)

实现
public interface Queue<T>{
    public abstract boolean isEmpty();
    public abstract boolean add(T x);
    public abstract T peek();
    public abstract T poll();
} 
顺序储存结构
public final class SeqQueue<T> implements Queue<T>{
    private Object element[];
    private int front,rear;
    public SeqQuene(int length){
        if(length<64){
            length = 64;
        }
        this.element = new Object[length];
        this.front = this.rear = 0;
    }
    public SeqQueue(){
        this(64);
    }
    public boolean isEmpty(){
        return this.front = this.rear;
    }
    public boolean add(T x){
        if(x==null){
            return false;
        }
        if(this.front==(this.rear+1)%this.element.length){
            Object[] temp = this.element;
            this.element = new Object[temp*2];
            int j = 0;
            for(int i=this.front;i!=this.rear;i=(i+1)%temp.length){
                this.element[j++] = temp[i];
            }
            this.front = 0;
            this.rear= j;
        }
        this.element[this.rear] = x;
        this.rear = (this.rear+1)%this.element.length;
        return true;
    }
    public T peek(){
        reutnr this.isEmpty()?null:(T)this.element[this.front];
    }
    public T poll(){
        if(this.isEmpty()){
            return null;
        }
        T temp = (T)this.element[this.front];
        this.front = (this.rear+1)%this.element.length;
        return temp;
    }
} 

数组和广义表

由顶点集合及顶点间及顶点间关系集合组成的一种数据结构

无向图

没有方向,边用无序对表示

有向图

边有方向,每条边用有序对表示

完全图

边的数量达到最大值

无向图

n*(n-1)/2

有向图

n*(n-1)

带权图

边具有权值

也成为网络

邻接顶点

一条边中的两个顶点

  • 度为零称为孤立点

  • 度为一称为悬挂点

在有向图中有入度和出度的区别

度为入度加出度

无向图边数等于所有顶点度的和的二分之一

有向图所有顶点的入度之和等于出度之和等于边数

子图

顶点和边为子集

当顶点相同时,为生成子图

连通性

一个顶点到另一顶点有路径则连通

图任意一个顶点到另一顶点连通则图连通

非连通图的极大连通子图为一个连通分量

当任意一个顶点到另一顶点连通且存在一条返回的路径则为强连通

路径

实现

矩阵类
public class Matrix {                                      
	private int rows,columns;
	private int[][] elements;
	public Matrix(int m,int n) {
		this.elements = new int[m][n];
		this.rows = m;
		this.columns = n;
	}
	public Matrix(int m,int n,int[][] value) {
		this.elements = new int[m][n];
		this.rows = m;
		this.columns = n;
		for(int i=0; i<value.length&&i<m; i++) {
			for(int j=0; j<value[i].length&&j<n; j++) {
				this.elements[i][j] = value[i][j]; 
			}
		}
	}	
	public Matrix(int n) {
		this(n,n);
	}
	public int getRows() {
		return this.rows;
	}
	public int getColumns() {
		return this.columns;
	}
	public int get(int m,int n) {
		if(m>=0&&m<rows&&n>=0&&n<columns) {
			return this.elements[m][n];
		}
		throw new IndexOutOfBoundsException("超出矩阵行数或列数");
	}
	public void set(int m, int n, int x) {
		if(m>=0&&m<rows&&n>=0&&n<columns) {
			this.elements[m][n] = x;
		}
		else throw new IndexOutOfBoundsException();
	}
	public String toString() {
		String str = " 矩阵" + this.getClass().getName()+"("+this.rows+" * "+this.columns+"): \n";
		for(int i=0;i<this.rows;i++) {
			for(int j=0;j<this.columns;j++) {
				str+=String.format("%6d", this.elements[i][j]);
			}
			str += "\n";
		}
		return str;
	}
	public void setRowsColumns(int m,int n) {
		
	}
	public boolean equals(Matrix mat) {
		
		if(elements.length!=mat.rows||elements[0].length!=mat.columns) {
			return false;
		}
		else {
			for(int i=0; i<elements.length; i++) {
				for(int j=0; j<elements[0].length; j++) {
					if(elements[i][j]!=mat.elements[i][j]) {
						return false;
					}
				}
			}
			return true;
		}
	}
	public boolean isSymmetric() {
		int i = 1,j = 0;
		if(elements.length!=elements[0].length) {
			return false;
		}
		for(;i<elements.length;i++) {
			for(;j<i;j++) {
				if(elements[i][j]!=elements[j][i]) {
					return false;
				}
			}
		}
		return true;
	}
邻接矩阵

顺序储存结构

使用线性表储存

//顶点类,线性表储存顶点
public abstract class AbstractGraph<T>{
	protected static final int MAX_WEIGHT = 0x0000ffff;
    protected SeqList<T> vertexlist;
    public AbstractGraph(int length){
        this.vertexlist = new SeqList<T>(length);
    }
    public AbstractGraph(){
        this(10);
    }
    public int vertexCount(){
        return this.vertexlist.size();
    }
    public String toString(){
        return "顶点集合:"+ this.vertexlist.toString()+"\n";
    }
    public void setVertex(int i, T x){
        this.vertexlist.set(i,x);
    }
    public abstract int insertVertex();
    public abstract void removeVertex();
    public abstract int weight(int i,int j);
    public abstract int next(int i,int j);
}
//边类
//图(起点序号,终点序号,权值)
public class Triple implements Comparable<Triple>, Addible<Triple> {
	public int row,column,value;
	public int getRow() {
		return row;
	}
	public void setRow(int row) {
		this.row = row;
	}
	public int getColumn() {
		return column;
	}
	public void setColumn(int column) {
		this.column = column;
	}
	public int getValue() {
		return value;
	}
	public void setValue(int value) {
		this.value = value;
	}
	public Triple(int row,int column,int value) {
		if(row>=0&&column>=0) {
			this.row = row;
			this.column = column;
			this.value = value;
		}
		else throw new IllegalArgumentException("");
	}
	public Triple(Triple tri) {
		this(tri.row, tri.column, tri.value);
	}
	public Triple() {
		this(0,0,0);
	}
	@Override
	public void add(Triple tri) {
		if(this.compareTo(tri)==0) {
			this.value += tri.value;
		}else {
			throw new IllegalArgumentException();
		}
		
	}
	public String toString() {
		return "("+row+","+column+","+value+")";
	}
	@Override
	public boolean removable() {
		return this.value==0;
	}
	@Override
	public int compareTo(Triple o) {
		// TODO Auto-generated method stub
		if(this.row<o.row) {
			return -1;
		}else if(this.row==o.row&&this.column==o.column){
			return 0;	
		}else if(this.row==o.row&&this.column==o.column) {
			return -1;
		}else {
			return 1;
		}
	}  
	public boolean equals(Triple tri) {
		if(this.row==tri.row&&this.column==tri.column&&this.value==tri.value) return true;
		else return false;
	}
	public Triple toSymmetry() {
		return new Triple(this.column,this.row,this.value);
	}
}
public class MatrixGraph<T> extends AbatractGraph<T>{
	private SeqList<T> vertexlist;
	private Matrix adjaMatrix;
	public int vertexCount() {
		return this.vertexlist.size();
	}
	
	public int weight(int i, int j) {
		return this.adjaMatrix.get(i, j);
	}
	public T getVertex(int i) {
		return this.vertexlist.get(i);
	}
	public MatrixGraph(SeqList<T> vertexlist, Matrix adjaMatrix) {						     	if(vertexlist.size()!=adjaMatrix.getRows()||vertexlist.size()!=adjaMatrix.getColumns())					 {	
			throw new IndexOutOfBoundsException("");
		}
		this.vertexlist = vertexlist;
		this.adjaMatrix = adjaMatrix;
	}			
	
	public MatrixGraph() {
		vertexlist = new SeqList<T>(10);		
		adjaMatrix = new Matrix(10);
	}	
}
  • 插入

    • public void insertEdge(int i,int j,int weight){
          if(!j=i){									
              if(weight<=0||weight>MAX_WEIGHT){		//当不成环且权值有效时
                  weight = MAX_WEIGHT;
              }
              this.matrix.set(i,j,weight);			//设置矩阵权值表示边
              
          }else throw new IllegalArgunmentException("不能成环");
          public void insertEdge(Triple edge){
              this.insertEdge(edge.row,edge.column,edge.value);//用边类的三元组设置边
          }
      }
      
  • 删除

    • public void removeEdge(int i,int j){
          if(i!=j)
              this.matrix.set(i,j,MAX_WEIGHT);
          
      }
      public void removeEdge(Triple edge){
          this.removeEdge(edge.row,edge.column);
      }
      
顶点
  • 插入

    • public int insertVertex(T x){
          int i = this.vertexlist.size(x);
          if(i>=this.matrix.getRow()){
              this.matrix.setRowColumns(i+1,i+1);
          }
          for(int j=0;j<i;j++){
              this.matrix.set(i,j,MAX_WEIGHT);
              this.matrix.set(j,i,MAX_WEIGHT);
          }
          return i;
      }
      
  • 删除

    • public void removeVertex(int i){
          int n = this.vertexCount();
          if(i>=0&&i<n){
              this.vertexlist.remove(i);
              for(int j=i+1;j<n;j++){
                  for(int k=0;k<n;k++){
                      this.matrix.set(j-1,k,this.matrix.get(j,k));//邻接矩阵少一行一列
                  }
              }
              this.matrix.setRowColumns(n-1,n-1);
          }else throw new IndexOutOfBoundsException("i = "+i);
      }
      
  • 获得邻接顶点和边的权值

    • //获得权值
      public int weight(int i,int j){
          return this.matrix.get(i,j);//返回矩阵中的值
      }
      
      protected int next(int i,int j){
          int n = this.vertexlistCount();
          if(i>=0&&i<n&&j>=-1&&j<n&&i!=j){    //检查是否成环,i在矩阵内,j符合条件
              for(int k=j+1;k<n;k++){
                  if(this.matrix.get(i,k)!=0&&this.matrix.get(i,k)!=MAX_WEIGHT){
                      return k;
                  }
              }
          }
          return -1;
      }
      
邻接表
实现
//链表储存矩阵实现
public class LinkedMatrix{
	private int rows,columns;
    SeqList<PolySinglyList<Triple>> rowlist;
    public LinkedMatrix(int i,int n){
        if(m>0&&n>0){
            this.rows = m;
            this.columns = n;
            this.rowlist = new SeqList<PolySinglyList<Triple>>();
            for(int i=0;i<m;i++){
                this.rowlist.insert(new PolySinglyList<Triple>>());
            }
        }else throw new IllegalArgunmentException("矩阵行列数不能小于零");
    }
    public LinkedMatrix(int m){
        this(m,m);
    }
    public LinkedMatrix(int m,int n,Triple[] tris){
        this(m,n);
        for(int i=0;i<this.length;i++){
            this.set(tri[i]);
        }
    }
    public int getRows()
    public int getColumns()
    
}
public class AdjListGraph<T> extends AbstractGraph<T>{
	protected LinkedMatrix adjlist;
    public AdjListGtrph(int length){
        super(length);
        this.adjlist = new LinkedMatrix(length,length);
    }
    public AdjListGraph(){
        this(10);
    }
    public AdjListGraph(T[] vertices){
        this(vertices.length);
        for(int i=0;i<vertices.length;i++){
            this.insertVertex(vertices[i]);
        }
    }
    public AdjListGraph(T[] vertexlist,Triple[] edges){
        this(vertices);                     //用数组构建含有数组元素的顺序表
        for(int i=0;i<edges.length;i++){
            this.insertEdge(edges[i]);
       }  
    }
    public String toString(){
        
    }
}
  • 插入

    • public void insertEdge(int i,int j,int weight){
      	if(i!=j){
              if(weight<=0||weight>=MAX_WEIGHT){
                  weight = 0;
              }
              this.adjlist.set(i,j,weight);
          }else throw new IllegalArgumentException("不可成环");
      }
      public void insertEdge(Triple edge){
          this.insertEdge(edge.getRow(),edge.getColumn(),edge.getValue());
      }
      
  • 删除

    • public void removeEdge(int i,int j){
      	if(i!=j){
      		this.adjlist.set(new Triple(i,j,MAX_WEIGHT));
      	}
      }
      public void removeEdge(Triple edge){
      	this.removeEdge(edge.getRow(),edge.getColumn(),edge.getValue());
      }
      
顶点
  • 插入

    • public int insertVertex(T x){
          int i = this.vertexlist.insert(x);
          if(i>=this.adjalist.getRows()){
              this.adjlist.setRowsColumns(i+1,j+1);
          }
          return i;
      }
      
  • 删除

    • public void removeVertex(int i){
      	int n= this.vertexCount();
      	if(i>=0&&i<n){
      		SortedSinglyList<Triple> link = this.adjlist.rowlist.get(i);
      		for(Node<Triple> p=link.head.next;p!=null;p=p.next){
      			this.removeEdge(p.data.toSymmetry());
      		}
      		n--;
      		this.adjlist.remove(i);
      		this.adjlist.setRowsColumns(n,n);
      		for(int j=0;j<n;j++){
      			link = this.adjlist.rowlist.get(j);
      			for(Node<Triple> p=link;p!=null;p=p.next){
                      if(p.data.row>i){
                          p.data.row--;
                      }
                      if(p.data.column>i){
                          p.data.column--;
                      }
                  }
      		}
              this.vertexlist.remove(i);
      	}else throw new IndexOutOfBoundsException("");
      }
      
  • 获得邻接顶点获得邻接顶点和边的权值

    • public int weight(int i,int j){
          if(i==j){
              return 0;
          }
          int weight = this.adjlist.get(i,j);
          return weight!=0?weight:MAX_WEIGHT;
      }
      protected int next(int i,int j){
          int n= this.vertexCount();
          if(i>=0&&i<n&&j>=-1&&j<n&&i!=j){
              SortedSinglyList<Triple> link = new this.adjlist.rowlist.get(i);
          	Node<Triple> find = link.head.next;
          	if(j==-1){
                  return find!=null?find.data.column:-1;
              }
              find = link.search(new Triple(i,j,0));
              if(find!=null){
                  find = find.next;
                  if(find!=null){
                      return find.data.column;
                  }
              }
          }
          return -1;
      }
      
遍历
深度优先搜索
public void DFSTraverse(int i){
    boolean visited = new boolean[this.vertexCount()];
    int j = i;
    do{
        if(!visited[j]){
            System.out.print("{");
            this.depthfs(j,visited);
            System.out.print("}");
        }
        j = (j+1)%this.vertexCount();          //使j从1到vertexCOunt()再回到0
    }while(j!=i)
    System.out.println();
}
private void depthfs(int i,boolean[] visited){
    System.out.println(this.getVertex(i)+"");
    visited[i] =true;
    int j=this.next(i,-1);
    while(j!=i){
        if(!visited[j]){
     		depthfs(j,visited);                   //递归访问该顶点的邻接顶点
        }
        j = this.next(i,j);
    }
    
}
广度优先搜索
public void BFSTraverse(int i) {
		boolean[] visited = new boolean[this.vertexCount()];
		int j = i;
		do {
			if(!visited[j]) {
				System.out.print("{");
				breadthfs(j,visited);
				System.out.print("}");
			}
			j = (j+1)%this.vertexCount(); 
		}while(j!=i);
		System.out.println();
	}
	
	private void breadthfs(int i, boolean[] visited) {
		System.out.print(vertexlist.get(i)+"");
		visited[i] = true;
		SeqQuene<Integer> que = new SeqQuene<Integer>();
		que.add(i);
		while(!que.isEmpty()) {
			i = que.poll();
			for(int j=0;j<adjaMatrix.getColumns();j++) {
				if(adjaMatrix.get(i,j)!=0&&adjaMatrix.get(i, j)!=Integer.MAX_VALUE&&!visited[j]) {
					System.out.print(vertexlist.get(i)+" ");
					visited[j] = true;
					que.add(j);
				}
			}
		}
	}
最小生成树
prim算法
/*
讲已选择的顶点作为一个集合,选择对于这个集合来说权值最小的边进行连接将结点添加进集合
*/
public void minSpanTree() {
		Triple[] mst= new Triple[vertexCount()-1];
		for (int i=0; i<mst.length;i++) {
			mst[i] = new Triple(0,i+1,this.weight(0,i+1));
		}
		for (int i=0;i<mst.length;i++) {
			 int minweight = mst[i].value, min=i;
			 for (int j=i+1;j<mst.length;j++) {
				 if(mst[j].value<minweight) {
					 minweight=mst[j].value;
					 min = j;
				 }
			 }
			 Triple edge = mst[min];
			 mst[min]=mst[i];
			 mst[i] = edge;
			 int tv=edge.column;
			 for(int j=i+1;j<mst.length;j++) {
				 int v=mst[j].column;
				 int weight=this.weight(tv,v);
				 if(weight<mst[j].value){
					 mst[j]=new Triple(tv, v, weight);
				 }
			 }
		}
		System.out.print("\n最小生成树的边集合:");
		int mincost=0;
		for (int i=0; i<mst.length; i++) {
			 System.out. print(mst[i]+"");

			 mincost += mst[i].value;

			 System.out.println(", 最小代价为:"+mincost);
		}
	}
Kruskal算法
import java.until.Comparator
public class MinSpanTree{
    private Triple[] mst;
    private int cost = 0;
    public MinSpanTree(int n,Triple[] edge,Comparator<Triple> empr){
        this.mst = new Triple[n-1];
        Heap<Triple> minheap = new Heap<Triple>(true,edges,empr);
        UnionFindSet ufset = new UnionFindSet(n);
        System.out.println("并查集:"+ufset.toString()+"");
        int i=0;
        for(int j=0;j<n;j++){
            Triple minedge = minheap.removeRoot();
            System.out.print("最小边"+minedge.toString());
        	if(ufset.union(minedge.row,minedge.column)){
                this.mst[i++]=minedge;
                this.cost += minedge.value;
                System.out.println("插入边:"+minedge.toString()+"");
            }
        }
        
    }
    public String toString();
    private static void print(boolean table[])
}
最短路径
dijkstra算法
/*
前述数组S
dist数组
path数组 
*/

floyd算法

树是由n个结点组成的有限集合。n=0的树称为空树

  • 有一个特殊结点称为根结点,只有后继结点,没有前驱结点
  • 除根结点之外的其他结点分为m个互不相交的集合T0、T1、……Tm-1也具有树结构,也就是根的子树

术语

父母、孩子、兄弟结点
  • 一个结点子树的根节点称为其孩子
  • 相对的该结点是其孩子结点的父母结点
  • 拥有同一个父母结点的多个结点之间称为兄弟

结点拥有的子树的棵数

结点层次、树的高度

结点的层次是结点处于树中的层次位置,约定根结点的层次为1其他层次是其父母结点的层次加1

树的高度或深度是树中结点的最大层次数

边、路径、直径

连接两个结点的的有序对为边

从一个结点到另一个结点间的有序对集合

有序对数是路径长度

二叉树

性质
  1. 根结点层次为1,则二叉树第i层最多有2^(i-1)个结点(归纳法证明)
  2. 在高度为h的二叉树中,最多由2^h^-1个结点
  3. 叶子结点数为n0,2度结点数为n2,则n0=n2+1
    • 完全二叉树:具有2^h^-1个结点的二叉树
    • 满二叉树:一颗具有n个结点高度为h的二叉树。如果它的每个结点都与高度为h的满二叉树中序号为0~n-1结点一一对应,则为完全二叉树
  4. 一个具有n个结点的完全二叉树,其高度h = ==[log2n+]取整==+1(<h-1log2(n+1)=<h)
  5. 一颗具有n个结点的完全二叉树,对序号为i的结点
    • 若i=0,则i为根结点,无父母结点;i>0,则i的父母结点序号为==(i-1)/2== 取整
    • 若2i+1<n,则i的左孩子结点序号为2i+1,否则i无左孩子
    • 若2i+2<n,则i的右孩子结点序号为2i+2,否则i无右孩子
遍历
孩子优先
  1. 先根次序

    访问根节点,遍历左子树,遍历右子树

  2. 中根次序

    遍历左子树,访问根结点,遍历右子树

  3. 后根次序

    遍历左子树,遍历右子树,访问根结点

兄弟优先

按层次进行访问,每层从左至右访问同层结点,访问完后进入下一结点

实现
ADT BinaryTree<T>{
	boolean isEmpty()
    int size()
    int height()
    void predrder()
    void inorder()
    void postorder()
    void levelorder()
    BinaryNode<T> insert(T x)
    BinaryNode<T> insert(BinaryNode<T> p,boolean leftChild)
    void remove(Binary<T> parent,boolean leftChild)
    void clear()
    BinaryNode<T> search(T key)
    boolean contains(T key)
    int level(T key)
}
顺序储存结构

顺序储存结构不能反映二叉树的数据关系

非完全二叉树不能采用顺序储存结构

链式储存结构
//结点类
public class BinaryNode<T>{
    public T data;
    public BinaryNode<T> left,right;
    public BinaryNode(T data,BinaryNode<T> left,){
        this.data = data;
        this.left = left;
        this.right = right;
    }
    public BinaryNode(T data){
        this(data,null,null);
    }
    public String toString(){
        return this.data.toString();
    }
    public boolean isLeaf(){
        return this.left==null&&this.right==null;
    }
}
//二叉树类
public Class BinaryTree<T>{
    public BinaryNode<T> root;
    public BinaryTree(){
        this.root = null;
    }
    public boolean isEmpty(){
        return this.root==null;
    }
   
    //插入结点
    public BinaryNode<T> insert(T x){
        return this.root = new BinaryNode<T>(x,this.root,null);
    }
    public BinaryNode<T> insert(BinaryNode<T> parent,T x,boolean leftChild){
        if(x==null){
            return null;
        }
        if(leftChild){
            return parent.left = new BinaryNode<T>(x,parent,null);
        }else{
            return parent.right = new BinaryNode<T>(x,null,parent);
        }
    }
    
    public void remove(BinaryNode<T> parent,boolean leftChild){
        if(leftChild){
            parent.left = null;
        }else{
            parent.right = null;
        }
    }
    public void clear(){
        this.root = null;
    }
    //先序遍历
    public void proorder(){
        preorder(this.root);
        System.out.println();
        
    }
    private void preorder(BinaryNode<T> p){
        if(p!=null){
            System.out.print(p.data.toString()+"");
            preorder(p.left);
            preorder(p.right);
        }
    }
    
    //
    public String toString(){
        return toString(this.root);
    }
    private String toString(BinaryNode<T> p){
        if(p==null){
            return "^";
        }
        return p.data.toString()+" "+toString(p.left)+" "+toString(p.right);
    }
}
//构造二叉树

层次遍历

非递归先序遍历

线索二叉树

查找

平均查找长度ASL= 累加(pi*ci

pi查找概率

ci查找次数

顺序查找

基于遍历算法,逐一比较

ASL成功

(n+1)/2

ASL不成功

n

二分法查找
  • 顺序储存
  • 数据元素排序
复杂度

log2n

索引表分块索引
散列
二叉排序树
平衡二叉树

排序

插入排序

直接插入
描述

将设置排序子序列和未排序子序列

开始时,序列全在未排序序列中,不断选择未排序序列中的元素,放入已排序序列中,最后元素全在已排序序列中

分析

设有n个元素,需要执行n-1次,每次比较次数和移动次数和初始排列有关

最好情况下,序列已经排序,比较次数为n-1,移动次数为(2n-1)时间复杂度为O(n)

最坏情况下,序列完全相反,第i次插入元素比较i次,移动i+2次,时间复杂度为O(n^2^)

稳定

实现
public class Array{
    public static void insertSort(int[] key){
        for(int i=0;i<key.length;i++){
            int temp  = key[i];
            for(int j=0;j>=0&&temp<key[j];j++){
                key[j+1] = key[j];
            }
            key[j+1] = temp;
        }
    }
}
希尔排序
描述

将序列内相隔一定距离(增量)的元素组成分组,进行直接排序

增量初值一般为序列长度一半,之后每次增量减半,最后为1

组内元素逐次增多并排序

分析

三层循环实现

最外层循环变化delta进行扫描

内两层实现直接插入

实现
public class shellSort(int[] keys){
    for(int delta = keys.length/2;delta>0;delta/=2){
        for(int i = delta;i<keys.length;i++){
            int temp = key[i];
            for(int j=i-delta;j>=0&&temp<key[j];j-=delta){
                keys[j+delta] = key[j];
            }
            keys[j+delta] = temp;
        }
    }
}

交换排序

冒泡排序
描述

比较相邻的两个元素,如果反序就交换

分析

最好情况下,序列排序,只需要扫描一趟,时间复杂度O(n)

最坏情况下,序列反序,时间复杂度为O(n^2^)

实现
private static void swap(int[] keys,int i,int j){
    int temp= key[j];
    key[j] = key[i];
    key[i] = temp;
}
public static void bubbkeSort(int[] keys){
    bubbleSort(keys,true);
}
public static void bubbleSort(int[] keys,boolean asc){
    boolean exchange = true;
    for(int i=0;i<keys.length&&exchange;i++){
        exchange = false;
        for(int j=0;j<keys.length-i;j++){
            if(asc?keys[j]>keys[j+1]:keys[j]<keys[j+1]){
                swaq(keys,j,j+1);
                exchange = true;
            }
        }
    }
}
快速排序
描述

在序列中选择一个元素为基准值,每趟从序列的两端开始交换,将小于基准值得元素交换到序列前端,大于基准值得元素交换到序列后端

实现
public static void quickSort(int[] keys){
    quickSort(keys,0,keys.length-1);
}
private static void quickSort(int[] keys,int begin,int end){
    if(begin>=0&&begin<keys.length&&end>=0&&end<keys.length&&begin<end){
        int i =begin,j=end;
        int vot= keys[i];
        while(i!=j){
            while(i<j&&keys[i]>=vot){
                j--;
            }
            if(i<j){
                keys[i++] =keys[i];
            }
            while(i<j&&keys[i]<=vot){
                i++;
            }
            if(i<j){
                keys][j--] = keys[i];
        }
        keys[i] = vot;
        quickSort(keys,beging,j-1);
        quickSort(keys,i+1,end);
            
    }
}
分析

最好情况下,每趟排序将序列分成相近得两个子序列,时间复杂度O(n*log2n)

最坏情况下,每趟将序列分成长度差异很大的两个子序列,时间复杂度O(n^2^)

选择排序

直接选择排序
描述

在n个元素中选择最小得元素放在最前位置

实现
public static void SelectSort(int[] keys){
    for(int i=0;i<keys.length;i++){
        int min = i;
        for(int j= i+1;j<keys.length;j++){
            if(keys[j]<keys[min]){
                min = j;
            }
            if(min!=i){
                swaq(keys,i,j);
            }
        }
    }
}
分析

第i趟的比较次数为n-i次,移动次数与初始排序有关,时间复杂度为O(n^2^)

堆排序
描述

利用二叉树的结构,将序列用二叉树结构储存,并排序,形成最大/最小堆

实现
public static void heapSort(int[] keys){
    heapSort(keys,true);
}
public static void heapSort(int[] keys,boolean minheap){
    for(int i=keys.length/2;i>=0;i--){
        sift(keys,i,keys.length-1,minheap);
    }
    for(int i=keys.length;i>0;i--){
        swaq(keys,0,1);
        sift(keys,0,i-1,minheap);
    }
}
private static void sift(int[] keys,int parent,int end,boolean minheap){
    int child = 2*parent+1;
    int value = keys[parent];
    while(child<=end){
        if(child<end&&(minheap?keys[child]>keys[child+1]:keys[child]<keys[child+1])){
            child++;
        }
        if(minheap?value>keys[child]:value<keys[child]){
            keys[parent] = keys[child];
            parent = child;
            child = 2*parent+1;
        }else{
            break;
        }
        keys[parent] = value;
        print(keys);
    }
}

归并排序

描述

分而治之思想,将未排序序列分成若干组子序列对子序列进行排序,排序后合并

实现
private static void merge(int[] x,int[] y,int begin1,int begin2,int n){
    int i = begin1,j = begin2,k = begin1;
    while(i<begin1+n&&j<begin2+n&&j<x.length){
        if(x[i]<x[j]){
            y[k++] = x[i++];
            
        }else{
            y[k++] = x[j++];
        }
        while(j<begin1+n&&i<x.length){
            y[k++] = x[i++];
        }
        while(j<begin2&&j<x.length){
            y[k++] = x[j++];
        }
    } 
}
private static void mergepass(int[] x,int[] y,int n){
    for(int i=0;i<x.length;i+=2*n){
        merge(x,y,i,i+n,n);
    }
}
public static void mergeSort(int[] x){
    int[] y = new int[x.length];
    int n = 1;
    while(n<x.length){
        mergepass(x,y,n);
        n*=2;
        if(n<x.length){
            mergepass(y,x,n);
            n*=2;
        }
    }
}
分析

时间复杂度为O(n*log2n),空间复杂度为O(n)

归并排序稳定