排序相关的基本概念

快速排序、希尔排序、堆排序、直接选择排序不是稳定的排序算法。

基数排序、冒泡排序、直接插入排序、折半插入排序、归并排序是稳定的排序算法。

内排序:在排序期间数据对象全部放在内存中的排序

外排序:排序期间全部对象个数太多,不能同时存放在内存,必须根据排序过程的要求,不断在内外存中移动排序.

桶排序:适合max很小的情况

         1.建议一堆buckets

         2.遍历原始数组,并将数据放入到各自的buckets中

         3.对非空的buckets进行排序

         4.按照顺序遍历这些buckets并返回到原始数组中即可构成排序后的数组.

冒泡排序

 

import java.util.Random;

public class BubbleSort {
	public static void main(String[] args){
		Random rand =new Random(5);
		int score[]=new int[5];
		for(int i=0;i<5;i++)
			score[i]=rand.nextInt(100);
        for (int i = 0; i < score.length -1; i++){    //最多做n-1趟排序
            for(int j = 0 ;j < score.length - i - 1; j++){    //对当前无序区间score[0......length-i-1]进行排序(j的范围很关键,这个范围是在逐步缩小的)
                if(score[j] >score[j + 1]){    //把大的值交换到后面
                    int temp = score[j];
                    score[j] = score[j + 1];
                    score[j + 1] = temp;
                }
            }            
            System.out.print("第" + (i + 1) + "次排序结果:");
            for(int a = 0; a < score.length; a++){
                System.out.print(score[a] + "\t");
            }
            System.out.println("");
        }
            System.out.print("最终排序结果:");
            for(int a = 0; a < score.length; a++){
                System.out.print(score[a] + "\t");
       }
    }
}

 

 

 

 

 

归并排序算法思想:
分而治之(divide - conquer);每个递归过程涉及三个步骤
第一, 分解: 把待排序的 n 个元素的序列分解成两个子序列, 每个子序列包括 n/2 个元素.
第二, 治理: 对每个子序列分别调用归并排序MergeSort, 进行递归操作
第三, 合并: 合并两个排好序的子序列,生成排序结果.

 

public static void mergeSort(int[] a, int[] tmp, int left, int right) {
    if (left < right) {
      int mid = left + (right - left) / 2;
      mergeSort(a, tmp, left, mid);// 左排序
      mergeSort(a, tmp, mid + 1, right);// 右排序
      merge(a, tmp, left, mid + 1, right);// 左右合并
    }
  }
public static void merge(int[] a, int[] tmp, int left, int rightPos,
      int right) {
    int leftEnd = rightPos - 1;
    int tmpPos = left;
    int num = right - left + 1;
    while (left <= leftEnd && rightPos <= right) {
      if (a[left] < a[rightPos]) {
        tmp[tmpPos++] = a[left++];
      } else {
        tmp[tmpPos++] = a[rightPos++];
      }
    }
    while (left <= leftEnd) {
      tmp[tmpPos++] = a[left++];
    }
    while (rightPos <= right) {
      tmp[tmpPos++] = a[rightPos++];
    }
    for (int i = 0; i < num; i++, right--) {
      a[right] = tmp[right];
    }
  }


快速排序:随机选定一个元素作为轴值,利用该轴值将数组分为左右两部分,左边元素都比轴值小,右边元素都比轴值大,但他们不是完全排序的.在此基础上,分别对

 

左右两部分调用快速排序,使得左右部分完全排序.

 

 public void sort(int[] a,int low,int high){
         int start = low;
         int end = high;
         int key = a[low];
         while(end>start){
             //从后往前比较
             while(end>start&&a[end]>=key)  //如果没有比关键值小的,比较下一个,直到有比关键值小的交换位置,然后又从前往后比较
                 end--;
             if(a[end]<=key){
                 int temp = a[end];
                 a[end] = a[start];
                 a[start] = temp;
             }
             //从前往后比较
             while(end>start&&a[start]<=key)//如果没有比关键值大的,比较下一个,直到有比关键值大的交换位置
                start++;
             if(a[start]>=key){
                 int temp = a[start];
                 a[start] = a[end];
                 a[end] = temp;
             }
         //此时第一次循环比较结束,关键值的位置已经确定了。左边的值都比关键值小,右边的值都比关键值大,但是两边的顺序还有可能是不一样的,进行下面的递归调用
         }
         //递归
         if(start>low) sort(a,low,start-1);//左边序列。第一个索引位置到关键值索引-1
         if(end<high) sort(a,end+1,high);//右边序列。从关键值索引+1到最后一个
     }

 

希尔排序:将无序数组分割为若干子序列,子序列不是逐段分割的,而是相隔特定增量的子序列.对各个子序列进行插入排序,然后再选择一个更小的增量,再将数组分割为

 

多个子序列进行排序...最后选择增量为1,即使用直接插入排序,使最终数组成为有序.

------------------------------------------------------------------------------------------------------------------------------------------------------

二分查找

 

public class Efcz {
public static void main(String[] args) {
	int[] a={1,2,3,4,5,6,7,8,9};
	int value=binary(a,9);
	System.out.println(value);
}
public static int binary(int[] array,int value)
{
	int low=0;
	int high=array.length-1;
	while(low<=high){
		int middle=low+(high-value)/2;
		if(value==array[middle])
			return middle;
		if(value>array[middle])
			low=middle+1;
		if(value<array[middle])
			high=middle-1;
	}
	return -1;
}
}

 

 

------------------------------------------------------------------------------------

 

 

红黑树的五个性质:
1)每个结点要么是红的,要么是黑的。
2)根结点是黑的。
3)每个叶结点,即空结点(NIL)是黑的。
4)如果一个结点是红的,那么它的俩个儿子都是黑的。
5)对每个结点,从该结点到其子孙结点的所有路径上包含相同数目的黑结点。

--------------------------------------------------------------------------------------

 

入栈数为n,出栈数种类为1/(n+1)*c(2n,n)

--------------------------------------------------------------------------------------------------------------------------------------------------------------

从n个数中找出最小的k个数(n >> k),最优平均时间复杂度是?

.对前k个数,建立最大堆,对于后面N-k个数,依次和最大堆的最大数比较,如果小于最大数,则替换最大数,并重新建立最大堆。时间复杂度为O(N*logk)。

-------------------------------------------------------------------------------------------------------------------------------------------------------------

广度遍历用队列做辅助,深度遍历用栈做辅助.

----------------------------------------------------------------------------------------------------------------------------------------------

什么是二叉查找树,原理
二叉排序树(Binary Sort Tree)又称二叉查找树。它或者是一棵空树;或者是具有下列性质的二叉树:

(1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值;

(2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;

(3)左、右子树也分别为二叉排序树;
步骤:若根结点的关键字值等于查找的关键字,成功。
否则,若小于根结点的关键字值,递归查左子树。
若大于根结点的关键字值,递归查右子树。
若子树为空,查找不成功。

 哈夫曼树
给定n 个权值作为n 个叶子结点,构造一棵二叉树,若带权路径长度达到最小,称这样的二叉树为最优二
叉树,也称为哈夫曼树(Huffman tree)。
构造方法:
假设有n 个权值,则构造出的哈夫曼树有n 个叶子结点。n 个权值分别设为w1、w2、…、wn,则
哈夫曼树的构造规则为:
(1) 将w1、w2、…,wn 看成是有n 棵树的森林(每棵树仅有一个结点);
(2) 在森林中选出两个根结点的权值最小的树合并,作为一棵新树的左、右子树,且新树的根结点权
值为其左、右子树根结点权值之和;
(3)从森林中删除选取的两棵树,并将新树加入森林;
(4)重复(2)、(3)步,直到森林中只剩一棵树为止,该树即为所求得的哈夫曼树

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------