数据结构与算法
1. 链表与数组。
2. 队列和栈,出栈与入栈。
3. 链表的删除、插入、反向。
4. 字符串操作。
http://blog.csdn.net/WINCOL/article/details/4795369
5. Hash表的hash函数,冲突解决方法有哪些。
6. 各种排序:冒泡、选择、插入、希尔、归并、快排、堆排、桶排、基数的原理、平均时间复杂度、最坏时间复杂度、空间复杂度、是否稳定。
package com.algorithmz.sort.imple;
import com.algorithmz.sort.Sort;
/**
* 冒泡排序
* @author jianina
*
*/
public class BubbleSort extends Sort{
/**
* 简单冒泡排序
*/
@Override
public void sort(int[] array) {
for (int i = 0; i < array.length-1; i++) {
for (int j = i+1; j < array.length; j++) {
if(array[j]
array[i]=array[j];
array[j]=temp;
}
}
}
}
/**
* 优化算法2
* 优化不明显 ,反而比算法1还要慢
* @param array
*/
public void sort2(int[] array) {
for (int i = 0; i < array.length; i++) {
for (int j =array.length-2; j >=i; j--) {
if(array[j]>array[j+1]){
int temp =array[j];
array[j]=array[j+1];
array[j+1]=temp;
}
}
}
}
/**
* 优化算法3
* 只有当每个内循环排序完之后,便可以得出正确的排序结果,则后面的循环不再进行,
* 否则和算法1、算法2在时间上没有多大差别
* @param array
*/
public void sort3(int[] array) {
boolean flag=true;
for (int i = 0; i < array.length&&flag; i++) {
flag=false;
for (int j =array.length-2; j >=i; j--) {
if(array[j]>array[j+1]){
int temp =array[j];
array[j]=array[j+1];
array[j+1]=temp;
flag=true;
}
}
}
}
}
package com.algorithmz.sort.imple;
import com.algorithmz.sort.Sort;
public class SimpleSelectionSort extends Sort{
/**
* 选择排序算法
* 每个位置看准了最小的才进行转换位置,减少了多余的交换位置
* 20万条数据量,冒泡50秒,选择15秒
*/
@Override
public void sort(int[] array) {
// TODO Auto-generated method stub
int min;
for (int i = 0; i < array.length-1; i++) {
min=i;
for (int j = i+1; j < array.length; j++) {
if(array[j]
}
}
if(i!=min){
int temp=array[i];
array[i]=array[min];
array[min]=temp;
}
}
}
}
package com.algorithmz.sort.imple;
import com.algorithmz.sort.Sort;
/**
* 插入排序
* @author jianina
*
*/
public class InsertSort extends Sort{
@Override
public void sort(int[] array) {
// TODO Auto-generated method stub
for (int i = 1; i < array.length; i++) {
for (int j = i; j>0&&compare(array[j], array[j-1]); j--) {
changePostion(j,j-1, array);
}
}
}
public void sort2(int[] array){
int j;
for (int i = 2; i < array.length; i++) {
if(array[i]
for (j = i-1;array[j]>array[0]; j--) {
array[j+1]=array[j];
}
array[j+1]=array[0];
}
}
}
public void sort3(int[] array){
for (int i =1; i < array.length; i++) {
int key=array[i];
int j=i-1;
while(j>=0&&array[j]>key){
array[j+1]=array[j];
j-=1;
}
array[j+1]=key;
}
}
/**
* 递归实现
* @param array
*/
public void sort4(int[] array,int n){
if(n>1){
sort4(array,n-1);
}
if(array[n]
sort4(array, n-1);
}
}
}
package com.algorithmz.sort.imple;
import com.algorithmz.sort.Sort;
/**
* 希尔排序
* @author jianina
*
*/
public class ShellSort extends Sort{
@Override
public void sort(int[] array) {
int length=array.length;
int i, j, gap;
for (gap = length / 2; gap > 0; gap /= 2)
for (i = gap; i
changePostion(j, j + gap, array);
}
public void sort2(int[] array){
int length=array.length;
int i,j,gap;
for (gap= length/2;gap>0; gap/=2) {
for (i = gap; i
changePostion(j, j+gap, array);
}
}
}
}
}
package com.algorithmz.sort.imple;
import com.algorithmz.sort.Sort;
/**
* 归并排序
* @author jianina
*
*/
public class MergeSort extends Sort{
public static void main(String[] args) {
int[] array=new int[]{1,3,4,5,2,4,6,8};
merge(array, 0, 3, 7);
for (int i : array) {
System.out.println(i);
}
}
@Override
public void sort(int[] array) {
// TODO Auto-generated method stub
sort(array,0,array.length-1);
}
public void sort(int[] array,int p,int r) {
// TODO Auto-generated method stub
if(p
sort(array,p,q);
sort(array,q+1,r);
merge2(array, p, q, r);
}
}
public static void merge(int[] array,int p,int q,int r){
int n1=(q-p)+1;
int n2=r-q;
int[] d1=new int[n1+1];
int[] d2=new int[n2+1];
for(int i=0;i
}
for(int i=0;i
}
d1[n1]=Integer.MAX_VALUE;
d2[n2]=Integer.MAX_VALUE;
int i=0;
int j=0;
for(int k=p;k<=r;k++){
if(d1[i]<=d2[j]){
array[k]=d1[i];
i++;
}else{
array[k]=d2[j];
j++;
}
}
}
public static void merge2(int[] array,int p,int q,int r){
int n1=(q-p)+1;
int n2=r-q;
int[] d1=new int[n1];
int[] d2=new int[n2];
for(int i=0;i
}
for(int i=0;i
}
int i=0;
int j=0;
for(int k=p;k<=r;k++){
if(i>=n1){
array[k]=d2[j++];
continue;
}else if(j>=n2){
array[k]=d1[i++];
continue;
}
if(d1[i]<=d2[j]){
array[k]=d1[i];
i++;
continue;
}
if(d1[i]>d2[j]){
array[k]=d2[j];
j++;
continue;
}
}
}
}
package com.algorithmz.sort.imple;
7. 快排的partition函数与归并的Merge函数。
归并Merge
public static void merge2(int[] array,int p,int q,int r){
int n1=(q-p)+1;
int n2=r-q;
int[] d1=new int[n1];
int[] d2=new int[n2];
for(int i=0;i
}
for(int i=0;i
}
int i=0;
int j=0;
for(int k=p;k<=r;k++){
if(i>=n1){
array[k]=d2[j++];
continue;
}else if(j>=n2){
array[k]=d1[i++];
continue;
}
if(d1[i]<=d2[j]){
array[k]=d1[i];
i++;
continue;
}
if(d1[i]>d2[j]){
array[k]=d2[j];
j++;
continue;
}
}
}
快拍parttition
public int partition(int[] array,int low,int high){
int pivotkey=array[low];
while(low
while(low
high--;
}
if(low
changeCount++;
low++;
}
while(low
low++;
}
if(low
changeCount++;
high--;
}
}
array[low]=pivotkey;
return low;
}
8. 对冒泡与快排的改进。
冒泡优化:冒泡优化加上flag标识
package com.algorithmz.sort.imple;
import com.algorithmz.sort.Sort;
/**
* 快速排序
* @author jianina
*
*/
public class QuickSortM extends Sort{
public int max_length_insert_sort=7;
public InsertSort insertSort=new InsertSort();
@Override
public void sort(int[] array) {
// TODO Auto-generated method stub
sort(array, 0, array.length-1);
}
public void sort(int[] array,int low,int high) {
// TODO Auto-generated method stub
if(low
sort(array,low,pivoykey-1);
sort(array,pivoykey+1,high);
}
}
/**
* 优化1加上阈值,当数组长度低于阈值是采用插入排序
* @param array
* @param low
* @param high
*/
public void sort2(int[] array) {
// TODO Auto-generated method stub
sort(array, 0, array.length-1);
}
public void sort2(int[] array,int low,int high) {
// TODO Auto-generated method stub
int pivoykey;
if((high-low)>max_length_insert_sort){
pivoykey=partition(array, low, high);
sort2(array,low,pivoykey-1);
sort2(array,pivoykey+1,high);
}
else{
InsertSort.sort4(array);
}
}
public void sort3(int[] array) {
// TODO Auto-generated method stub
sort3(array, 0, array.length-1);
}
/**
* 优化2再加上阈值的同时,采用尾递归,减少递归深度
* @param array
* @param low
* @param high
*/
public void sort3(int[] array,int low,int high) {
// TODO Auto-generated method stub
int pivoykey;
if((high-low)>max_length_insert_sort){
while (low
sort3(array,low,pivoykey-1);
low=pivoykey+1;
}
}
else{
InsertSort.sort4(array);
}
}
/**while循环判断条件加不加等号情况分析:
* 不加双等 交换次数:378次,但是不加等号的速度最快
* 加一个双等 交换次数:174,
* 条件加双等 交换次数149,
*
*
*/
public int partition(int[] array,int low,int high){
int pivotkey=array[low];
while(low
while(low
high--;
}
if(low
low++;
}
while(low
low++;
}
if(low
high--;
}
}
array[low]=pivotkey;
return low;
}
}
9. 二分查找,与变种二分查找。
package com.algorithmz.binarysearch;
public class BinarySearch {
public static void main(String[] args) {
int[] array=new int[]{1,2,53,6,4,8};
System.out.println(binarySearch(array,-1));
}
public static int binarySearch(int[] a,int key) {
int low = 0;
int high = a.length - 1;
int mid = 0;
while(low <= high){
mid = (low + high) / 2;
if(a[mid] == key) return mid;
if(a[mid] > key) high = mid - 1;
if(a[mid] < key) low = mid + 1;
}
return -1;
}
10. 二叉树、B+树、AVL树、红黑树、哈夫曼树。
http://blog.sina.com.cn/s/blog_9cbb6a210102v5dc.html
http://blog.csdn.net/dongdong_java/article/details/9128983
http://blog.csdn.net/quitepig/article/details/8041308
11. 二叉树的前中后续遍历:递归与非递归写法,层序遍历算法。
package com.algorithmz.binarytree;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import java.util.Stack;
public class BinaryTree {
public static void main(String[] args) {
BinaryTree binaryTree=new BinaryTree();
binaryTree.createBinaryTree();
binaryTree.levelTravel(binaryTree.root);
}
private TreeNode root=null;
public BinaryTree(){
root=new TreeNode(1,"rootNode(A)");
}
public BinaryTree(TreeNode root){
this.root=root;
}
public void createBinaryTree(){
TreeNode b=new TreeNode(2,"B");
TreeNode c=new TreeNode(3,"C");
TreeNode d=new TreeNode(4,"D");
TreeNode e=new TreeNode(5,"E");
TreeNode f=new TreeNode(6,"F");
root.leftNode=b;
root.rightNode=c;
root.leftNode.leftNode=d;
root.leftNode.rightNode=e;
root.rightNode.rightNode=f;
}
public boolean isEmpty(){
return root==null;
}
public int height(){
return height(root);
}
public int height(TreeNode treeNode){
if(treeNode==null){
return 0;
}
int i=height(treeNode.leftNode);
int j=height(treeNode.rightNode);
return i
}
public int size(){
return size(root);
}
public int size(TreeNode treeNode){
if(treeNode==null){
return 0;
}
return 1+size(treeNode.leftNode)+size(treeNode.rightNode);
}
public void visted(TreeNode subTree){
subTree.isVisted=true;
System.out.println("key:"+subTree.key+" name:"+subTree.data);
}
/**
* 前序遍历
* @param subTree
*/
public void preOrder(TreeNode subTree){
if(subTree!=null){
visted(subTree);
preOrder(subTree.leftNode);
preOrder(subTree.rightNode);
}
}
/**
* 前序遍历
* @param subTree
*/
public void inOrder(TreeNode subTree){
if(subTree!=null){
inOrder(subTree.leftNode);
visted(subTree);
inOrder(subTree.rightNode);
}
}
public void postOrder(TreeNode subTree){
if(subTree!=null){
postOrder(subTree.leftNode);
postOrder(subTree.rightNode);
visted(subTree);
}
}
/**
* 二叉树非递归遍历实现
* @param subTree
*/
public void nonRecPreOrder(TreeNode subTree){
Stack
TreeNode node=subTree;
while(node!=null||stack.size()>0){
while(node!=null){
visted(node);
stack.push(node);
node=node.leftNode;
}
node=stack.pop();
node=node.rightNode;
}
}
/**
* 二叉树中序非递归遍历
* @param subTree
*/
public void nonRecInOrder(TreeNode subTree){
Stack
TreeNode node =subTree;
while(node!=null||stack.size()>0){
//存在左子树
while(node!=null){
stack.push(node);
node=node.leftNode;
}
//栈非空
if(stack.size()>0){
node=stack.pop();
visted(node);
node=node.rightNode;
}
}
}
public void nonRecPostOrder(TreeNode p){
Stack
TreeNode node =p;
while(p!=null){
//左子树入栈
for(;p.leftNode!=null;p=p.leftNode){
stack.push(p);
}
//当前结点无右子树或右子树已经输出
while(p!=null&&(p.rightNode==null||p.rightNode==node)){
visted(p);
//纪录上一个已输出结点
node =p;
if(stack.empty())
return;
p=stack.pop();
}
//处理右子树
stack.push(p);
p=p.rightNode;
}
}
/**
*
* @param root 树根节点
* 层序遍历二叉树,用队列实现,先将根节点入队列,只要队列不为空,然后出队列,并访问,接着讲访问节点的左右子树依次入队列
*/
public static void levelTravel(TreeNode root){
if(root==null)return;
Queue
q.add(root);
while(!q.isEmpty()){
TreeNode temp = q.poll();
System.out.println(temp.data);
if(temp.leftNode!=null)
q.add(temp.leftNode);
if(temp.rightNode!=null)
q.add(temp.rightNode);
}
}
/**
*
* @param root 树根节点
* 利用栈实现循环先序遍历二叉树
* 这种实现类似于图的深度优先遍历(DFS)
* 维护一个栈,将根节点入栈,然后只要栈不为空,出栈并访问,接着依次将访问节点的右节点、左节点入栈。
* 这种方式应该是对先序遍历的一种特殊实现(看上去简单明了),但是不具备很好的扩展性,在中序和后序方式中不适用
*/
public static void preOrderStack_1(TreeNode root){
if(root==null)return;
Stack
s.push(root);
while(!s.isEmpty()){
TreeNode temp=s.pop();
System.out.println(temp.data);
if(temp.rightNode!=null) s.push(temp.rightNode);
if(temp.leftNode!=null) s.push(temp.leftNode);
}
}
/**
*
* @param root 树的根节点
* 利用栈模拟递归过程实现循环先序遍历二叉树
* 这种方式具备扩展性,它模拟递归的过程,将左子树点不断的压入栈,直到null,然后处理栈顶节点的右子树
*/
public static void preOrderStack_2(TreeNode root){
if(root==null)return;
Stack
while(root!=null||!s.isEmpty()){
while(root!=null){
System.out.println(root.data);
s.push(root);//先访问再入栈
root=root.leftNode;
}
root=s.pop();
root=root.leftNode;//如果是null,出栈并处理右子树
}
}
/**
*
* @param root 树根节点
* 利用栈模拟递归过程实现循环中序遍历二叉树
* 思想和上面的preOrderStack_2相同,只是访问的时间是在左子树都处理完直到null的时候出栈并访问。
*/
public static void inOrderStack(TreeNode root){
if(root==null)return;
Stack
while(root!=null||!s.isEmpty()){
while(root!=null){
s.push(root);//先访问再入栈
root=root.leftNode;
}
root=s.pop();
System.out.println(root.data);
root=root.rightNode;//如果是null,出栈并处理右子树
}
}
/**
*
* @param root 树根节点
* 后序遍历不同于先序和中序,它是要先处理完左右子树,然后再处理根(回溯),所以需要一个记录哪些节点已经被访问的结构(可以在树结构里面加一个标记),这里可以用map实现
*/
public static void postOrderStack(TreeNode root){
if(root==null)return;
Stack
Map
s.push(root);
while(!s.isEmpty()){
TreeNode temp=s.peek();
if(temp.leftNode!=null&&!map.containsKey(temp.leftNode)){
temp=temp.leftNode;
while(temp!=null){
if(map.containsKey(temp))break;
else s.push(temp);
temp=temp.leftNode;
}
continue;
}
if(temp.rightNode!=null&&!map.containsKey(temp.rightNode)){
s.push(temp.rightNode);
continue;
}
TreeNode t=s.pop();
map.put(t,true);
System.out.println(t.data);
}
}
private static class TreeNode{
private int key;
private String data;
private boolean isVisted;
private TreeNode leftNode;
private TreeNode rightNode;
public TreeNode(){
}
public TreeNode(int key,String data){
this.key=key;
this.data=data;
}
public TreeNode(int key,String data,TreeNode leftNode,TreeNode rightNode){
this.key=key;
this.data=data;
this.leftNode=leftNode;
this.rightNode=rightNode;
}
}
}
12. 图的BFS与DFS算法,最小生成树prim算法与最短路径Dijkstra算法。
13. KMP算法。
http://blog.csdn.net/yutianzuijin/article/details/11954939
14. 排列组合问题。
15. 动态规划、贪心算法、分治算法。(一般不会问到)
16. 大数据处理:类似10亿条数据找出最大的1000个数.........等等
算法的话其实是个重点,因为最后都是要你写代码,所以算法还是需要花不少时间准备,这里有太多算法题,写不全,我的建议是没事多在OJ上刷刷题(牛客网、leetcode等),剑指offer上的算法要能理解并自己写出来,编程之美也推荐看一看。
推荐书籍:《大话数据结构》《剑指offer》《编程之美》