数据结构与算法,java

数据元素之间的相互关系称为结构
数据结构的本质:组织大量数据的方法。如何将现实世界中各种各样的数据放入到内存中,并且如何在内存中操作这些数据,如何评价这些存储方案和操作方法
将现实世界的数据组织成逻辑结构,再把逻辑结构的数据映射到物理结构(比如链表是逻辑线性,物理不连续的)
算法分析:算法运行的时间和空间估计

数据类型指的是一组值和一组对这些值的操作的集合。是组织信息的一种自然方式。
每当遇到逻辑上相关的不同类型的数据时,定义一个抽象数据类型。
抽象数据类型(ADT):一种能够对使用者隐藏数据表示的数据类型。(如用java类来实现抽象数据类型,用一组静态方法实现一个函数库)

常见数据结构:
线性:数组、链表、队列、堆栈、块状数组(数组+链表)、hash表、双端队列、位图(btimap);
树:堆(大顶堆、小顶堆),trie树(字母树or字典树)、后缀树、后缀数组、二叉排序/查找树、B+/B-,AVL树、Treap、红黑树等
图:

栈和队列都可以使用数组或链表实现。栈的操作在表(统称数组和链表)的末尾,队列在表的队尾和队头操作。当队列用数组实现时,保留一个数组以及front和back,以及队列中的元素个数currentSize。使用循环数组实现。

某些数据结构不是为了用户可访问的数据结构而建立的,通常用它们在程序中辅助实现一些算法。 栈、队列和树是抽象数据类型,它们由一些更加基础的数据结构如数组、链表来实现。这些ADT只提供给用户间的的接口,一般仅允许插入和访问或者删除一个数据项。

对于大量的数据,表的线性访问时间太慢。使用树。

堆(优先队列)是允许至少下列两种操作的数据结构:insert(enqueue)以及deleteMin(dequeue)。
实现堆的方法:使用一个简单链表在表头以O(1)执行插入,并遍历该链表以删除最小元,O(N)。或者让链表保持有序地执行插入;     使用二叉查找树,插入和查找的平均时间都是O(logN)。

完全二叉树:被完全填满的二叉树,有可能的例外是在底层,底层上的元素从左到右填入。
当堆不加修饰的出现在优先队列的上下文中时,数据结构为二叉堆。是一颗完全二叉树。完全二叉树的规律,使得它可以用一个数组表示而不需要链表。所以一个堆结构将由一个(Comparable对象的)数组和一个代表当前堆的大小的整数组成。  数组的array[0]空出来。
让操作快速执行的性质是堆序性质。

上滤:将一个元素X插入到堆中,在下一个可用位置创建一个空穴,如果X放在该空穴中而并不破坏堆的序,那么插入完成,否则,把空穴的父节点上的元素移入空穴中,这样,空穴就朝着根的方向上冒一步。
下滤:删除最小元素后,在根节点建立了一个空穴,堆中最后一个元素必须移动到该堆的某个地方。

package binary;

public class BinaryHeap 
      
      
       
       >{
	
	private int currentSize;
	private static final int DEFAULT_CAPACITY = 10;
	private Comparable [] array;

	public BinaryHeap() {
		this(DEFAULT_CAPACITY);
	}
	
	public BinaryHeap(int capacity) {
		currentSize = 0;
		array = new Comparable[capacity + 1];
	}
	
	public BinaryHeap(AnyType [] items) {
		currentSize = items.length;
		array = new Comparable[(currentSize+2)*11/10];
		int i = 1;
		for(AnyType item : items) {
			array[i++] = item;
		}
		buildHeap();
	}
	
	public void insert(AnyType x) {
		if(currentSize == array.length - 1) {
			 enlargeArray(array.length * 2 + 1);
		}
		int hole = ++currentSize;
		for(; hole>1 && x.compareTo((AnyType) array[hole/2]) < 0; hole = hole/2) {
			array[hole] = array[hole/2];
		}
		array[hole] = x;
	}
	
	public AnyType findMin() {
		if(isEmpty()) {
			return null;
		}
		return (AnyType) array[1];
		
	}
	
	public AnyType deleteMin() {
		if(isEmpty()) {
			return null;
		}
		AnyType minItem = findMin();
		array[1] = array[currentSize--];
		percolateDown(1);
		
		return minItem;
	}
	
	public boolean isEmpty() {
		return currentSize == 0;
		
	}
	
	public void makeEmpty() {
		
	}
	
	private void percolateDown(int hole) {
		int child;
		AnyType tmp = (AnyType) array[hole];
		for(; hole*2<=currentSize; hole = child) {
			child = hole*2;
			if(child != currentSize && array[child+1].compareTo(array[child])<0) {
				child++;
			}
			if(array[child].compareTo(tmp) < 0) {
				array[hole] = array[child];
			} else 
				break;
		}
		array[hole] = tmp;
	}
	
	private void buildHeap() {
		for(int i = currentSize / 2; i > 0; i--) {
			percolateDown(i);
		}
		
	}
	
	private void enlargeArray(int newSize) {
		Comparable [] array1 = new Comparable[newSize];
		int i = 0;
		for(Comparable item : array) {
			array1[i] = item;
			i++;
		}
		array = array1;
	}
	
}

      
      


二叉查找树:每个节点X,它的左子树中所有项的值小于X中的项,而它的右子树中所有项的值大于X中的项。

package binary;

public class BinaryHeap 
       
       
        
        >{
	
	private int currentSize;
	private static final int DEFAULT_CAPACITY = 10;
	private Comparable [] array;

	public BinaryHeap() {
		this(DEFAULT_CAPACITY);
	}
	
	public BinaryHeap(int capacity) {
		currentSize = 0;
		array = new Comparable[capacity + 1];
	}
	
	public BinaryHeap(AnyType [] items) {
		currentSize = items.length;
		array = new Comparable[(currentSize+2)*11/10];
		int i = 1;
		for(AnyType item : items) {
			array[i++] = item;
		}
		buildHeap();
	}
	
	public void insert(AnyType x) {
		if(currentSize == array.length - 1) {
			 enlargeArray(array.length * 2 + 1);
		}
		int hole = ++currentSize;
		for(; hole>1 && x.compareTo((AnyType) array[hole/2]) < 0; hole = hole/2) {
			array[hole] = array[hole/2];
		}
		array[hole] = x;
	}
	
	public AnyType findMin() {
		if(isEmpty()) {
			return null;
		}
		return (AnyType) array[1];
		
	}
	
	public AnyType deleteMin() {
		if(isEmpty()) {
			return null;
		}
		AnyType minItem = findMin();
		array[1] = array[currentSize--];
		percolateDown(1);
		
		return minItem;
	}
	
	public boolean isEmpty() {
		return currentSize == 0;
		
	}
	
	public void makeEmpty() {
		
	}
	
	private void percolateDown(int hole) {
		int child;
		AnyType tmp = (AnyType) array[hole];
		for(; hole*2<=currentSize; hole = child) {
			child = hole*2;
			if(child != currentSize && array[child+1].compareTo(array[child])<0) {
				child++;
			}
			if(array[child].compareTo(tmp) < 0) {
				array[hole] = array[child];
			} else 
				break;
		}
		array[hole] = tmp;
	}
	
	private void buildHeap() {
		for(int i = currentSize / 2; i > 0; i--) {
			percolateDown(i);
		}
		
	}
	
	private void enlargeArray(int newSize) {
		Comparable [] array1 = new Comparable[newSize];
		int i = 0;
		for(Comparable item : array) {
			array1[i] = item;
			i++;
		}
		array = array1;
	}
	
}

       
       


AVL树:其每个节点的左子树和右子树的高度最多差1的二叉查找树(空树的高度定义为-1)

package binary;

/*
 * 把需要重新平衡的节点叫做t,出现的高度不平衡需要t节点的两棵子树的高度差为2,不平衡出现的情况:
 * 1、对t的左儿子的左子树进行一次插入;
 * 2、对t的左儿子的右子树进行一次插入;
 * 3、对t的右儿子的左子树进行一次插入;
 * 4、对t的右儿子的右子树进行一次插入;
 * 其中1和4对称,只需要单旋转;2和3对称,需要双旋转。
 * 双旋转是先在t的儿子和孙子之间旋转而后再在t和它的新儿子之间旋转的结果
 */
public class AvlNode
      
      
       
       > {
	AnyType element;
	AvlNode
       
       
        
         left;
	AvlNode
        
        
         
          right;
	int height;
	
	public AvlNode(AnyType theElement) {
		this(theElement, null, null);
	}

	public AvlNode(AnyType theElement, AvlNode
         
         
          
           lt,
			AvlNode
          
          
            rt) { this.element = element; this.left = lt; this.right = rt; this.height = 0; } private int height(AvlNode 
           
             t) { return t == null ? -1 : t.height; } private AvlNode 
            
              insert(AnyType x, AvlNode 
             
               t) { if(t == null) { return new AvlNode 
              
                (x); } int comResult = x.compareTo(t.element); if(comResult < 0) { t.left = insert(x, t.left); if(height(t.left) - height(t.right) == 2) { if(x.compareTo(t.left.element) < 0) { t = rotateWithLeftChild(t); } else { t = doubleWithLeftChild(t); } } }else if(comResult > 0) { t.right = insert(x, t.right); if(height(t.right) - height(t.left) == 2) { if(x.compareTo(t.right.element) > 0) { t = rotateWithRightChild(t); } else { t = doubleWithRightChild(t); } } } t.height = Math.max(height(t.left), height(t.right)) + 1; return t; } private AvlNode 
               
                 rotateWithLeftChild(AvlNode 
                
                  k2) { AvlNode 
                 
                   k1 = k2.left; k2.left = k1.right; k1.right = k2; k2.height = Math.max(height(k2.left), height(k2.right)) + 1; k1.height = Math.max(height(k1.left), height(k2)) + 1; return k1; } private AvlNode 
                  
                    doubleWithLeftChild(AvlNode 
                   
                     k3) { k3.left = rotateWithRightChild(k3.left); return rotateWithLeftChild(k3); } private AvlNode 
                    
                      rotateWithRightChild(AvlNode 
                     
                       k2) { AvlNode 
                      
                        k1 = k2.right; k2.right = k1.left; k1.left = k2; k2.height = Math.max(height(k2.left), height(k2.right)) + 1; k1.height = Math.max(height(k1.right), height(k2)) + 1; return k1; } private AvlNode 
                       
                         doubleWithRightChild(AvlNode 
                        
                          k3) { k3.right = rotateWithLeftChild(k3.right); return rotateWithRightChild(k3); } } 
                         
                        
                       
                      
                     
                    
                   
                  
                 
                
               
              
             
            
          
         
         
        
        
       
       
      
      


常见算法:
基本思想:枚举、递归、分治、模拟、贪心、动态规划、剪枝、回溯
图算法:深度优先遍历与广度优先遍历、最短路径、最小生成树、拓扑排序
字符串算法:字符串查找、哈市、算法、KMP算法
排序算法:冒泡、插入、选择、快速排序、归并排序、堆排序、桶排序
动态规划:背包问题、最长公共子序列、最优二分检查树
数论问题:素数问题、整数问题、进制转换、同余模运算
排列组合:排列和组合算法



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值