常考知识点,记忆技巧:
1、平均时间:快速排序、希尔排序、归并排序和堆排序为 O(nlog2n),,其他都是n的平方。故事助记:
快(快速)些(希尔)以O(nlog2n),的速度归(归并)队(堆)。
2、最坏时间:快速排序o(n的平方),其他都是和平均时间相同。
3、空间复杂度:快速排序o(log2n),归并排序o(n),基数排序 o(d),其他都是o(1).
4、算法稳定性:快速排序、希尔排序、简单选择排序、堆排序,这四种不稳定的,其他的都稳定
一句话记忆:考研复习痛苦,心情
不稳定,
快(快速)些(希尔)选(选择)一堆(堆排序)好友来聊天。
5、直接插容易变成o(n),冒泡冒得好o(n),
起得好,容易
插,都是指初始序列有序。
6、经过一趟排序,能够保证一个元素到达最终位置,这样的排序是交换类(快速排序,冒泡排序)和选择类(简单选择排序、堆排序)
7、排序方法的元素比较次数和原始序列无关----简单选择排序,折半插入排序。
8、排序方法的排序堂叔和原始序列有关-----交换类的排序(快速排序和冒泡排序)
9、堆排序比较适合找出前几大的数。
import java.util.HashMap;
import java.util.Random;
public class sortCategory {
public static void main(String[] args){
HashMap<Object,Object> map=new HashMap<Object,Object>();
Random random=new Random();
Object[] sorts1=new Object[100];
int[] sorts=new int[100];
System.out.println("排序前:");
int i=0;
while(map.size()<sorts1.length){
map.put(random.nextInt(1000)+1, i);
}
sorts1=map.keySet().toArray();//转换成数组
for(i=0;i<sorts1.length;i++){
sorts[i]=(int)sorts1[i];
}
for(i=0;i<sorts.length;i++){
System.out.print(sorts[i]+" ");
}
//选择排序
selectSort(sorts);
System.out.println();
System.out.println("选择算法排序后:");
for( i=0;i<100;i++){
System.out.print(sorts[i]+" ");
}
//把节点搞成完全二叉树的存储方式,从下标1开始存
int[] sorts2=new int[100];
for(i=0;i<sorts.length;i++){
sorts2[i]=(int)sorts1[i];
}
heapSort(sorts2);
System.out.println();
System.out.println("堆排序算法排序后:");
for( i=0;i<100;i++){
System.out.print(sorts2[i]+" ");
}
bubbleSort(sorts2);
System.out.println();
System.out.println("冒泡排序算法排序后:");
for( i=0;i<100;i++){
System.out.print(sorts2[i]+" ");
}
quickSort(sorts2,0,sorts2.length-1);
System.out.println();
System.out.println("快速排序算法排序后:");
for( i=0;i<100;i++){
System.out.print(sorts2[i]+" ");
}
insertSort(sorts2);
System.out.println();
System.out.println("直接插入排序算法排序后:");
for( i=0;i<100;i++){
System.out.print(sorts2[i]+" ");
}
halfInsertSort(sorts2);
System.out.println();
System.out.println("折半插入排序算法排序后:");
for( i=0;i<100;i++){
System.out.print(sorts2[i]+" ");
}
shellSort(sorts2);
System.out.println();
System.out.println("希尔排序算法排序后:");
for( i=0;i<100;i++){
System.out.print(sorts2[i]+" ");
}
int[] tempSort=new int[100];
mergeSort(sorts2,tempSort,0,sorts2.length-1);
System.out.println();
System.out.println("归并排序算法排序后:");
for( i=0;i<100;i++){
System.out.print(sorts2[i]+" ");
}
jiShuSort(sorts2,3);
System.out.println();
System.out.println("基数排序算法排序后:");
for( i=0;i<100;i++){
System.out.print(sorts2[i]+" ");
}
}
/**
* 选择排序
*/
/**
* 选择排序,从头到尾顺序扫描,找出最小的一个记录,和第一个记录交换,
* 共需选择n-1次,由于最后一次只剩一个,无需选择
* @param R
*/
public static void selectSort(int[] R){
int temp=0;//用于交换
int min=0;//用于标志最小值的下标
for(int i=0;i<R.length-1;i++){
min=i;
for(int j=i;j<R.length;j++){
if(R[min]>R[j])
min=j; //记录最小值得下标
}
//交换两个数
temp=R[min];
R[min]=R[i];
R[i]=temp;
}
}
/**
* 堆排序子方法
* 1、先初始化堆,然后进行选择
* 由于R[]组里边是一颗完全二叉树,所以元素存储必须从1开始
*/
private static void sift(int[] R,int low,int high)
{ int i=low,j=2*i+1;//i标志根节点,j表示左节点。
int temp=R[i];//temp等于根节点;
while(j<high){
if(j+1<high&&R[j]<R[j+1])
++j; //如果右节点比左节点大,那么j指向右结点
if(R[j]>temp){//如果根节点比右节点小,那么交换
R[i]=R[j];
i=j;//右节点作为根节点
j=2*i+1;//j等于左孩子节点
}else
break;
}
R[i]=temp;//被调整的值放到最终位置上
}
/**
* 堆排序
* @param R
* @param n
*/
public static void heapSort(int[] R){
int i=0;
int temp=0; //用于交换数据
for(i=R.length/2-1;i>=0;--i) //建堆过程
sift(R,i,R.length);
for(i=R.length-1;i>=1;--i){ //对堆进行n-1趟排序
temp=R[0];
R[0]=R[i];
R[i]=temp;
sift(R,0,i-1);//对剩下的i-1个元素进行堆调整
}
}
/**
* 冒泡排序
*/
public static void bubbleSort(int[] R){
int temp;
for(int i=0;i<R.length;i++){
for(int j=0;j<R.length-1-i;j++){
if(R[j]>R[j+1]){
temp=R[j];
R[j]=R[j+1];
R[j+1]=temp;
}
}
}
}
/**
* 快速排序
*/
public static void quickSort(int[] R,int left,int right){
if(left<right){
int key=R[left];
int low=left,high=right;
while(low!=high){
while(low<high&&R[high]>key) high--;//如果右边的数都大于key,那么指针一直往左走
R[low]=R[high];
while(low<high&&R[left]<key) low++;//如果左边的数都小于key,那么指针一直往右走
R[high]=R[low];
}
R[low]=key;//一趟快速排序后,数组被分成两部分,此时low=high
quickSort(R,left,low-1);
quickSort(R,low+1,right);
}
}
/**
* 直接插入排序
*/
public static void insertSort(int[] R){
int temp=0;
int j=0;
for(int i=1;i<R.length;i++){ //表示第一趟已经有序
temp=R[i];
for(j=i;j>0;j--){
if(temp<R[j-1]){
R[j]=R[j-1];
}else
break;
}
R[j]=temp;
}
}
/**
* 折半插入排序算法
*/
public static void halfInsertSort(int[] R){
int temp=0;
int low=0,high=0,mid=0;
for(int i=1;i<R.length;i++){ //表示第一趟已经有序
temp=R[i];
low=0;
high=i-1;
while(low<=high){//通过折半循环可以找到元素要插入的位置
mid=(low+high)/2;
if(temp<R[mid])
high=mid-1;
else low=mid+1;
}
for(int j=i;j>low+1;j--)
R[j]=R[j-1];
R[low]=temp;//插入元素
}
}
/**
* 希尔排序(Shell)算法
*/
public static void shellSort(int[] R){
int step=R.length/2; //取增量
int temp=0;//临时空间
while(step>=1){
//无须序列
for(int i=step;i<R.length;i++){
temp=R[i];//增量小区间的最后一个数
int j=0;
for(j=i-step;j>=0;j=j-step){
if(temp<R[j])
R[j+step]=R[j];//排序
else break;
}
R[j+step]=temp;
}
step=step/2;//再次取增量
}
}
/**
* 归并排序算法
*/
public static void mergeSort(int[]R,int[] tempR,int left, int right){
if(left<right){
int middle=(left+right)/2;//取分割位置
mergeSort(R,tempR,left,middle); //递归划分数组左序列
mergeSort(R,tempR,middle+1,right);//递归划分数组右序列
merge(R,tempR,left,middle+1,right);//数组合并操作
}
}
/**
*
* @param R 待排序数组
* @param tempR 临时数组
* @param left 第一个 区间段开始位置
* @param middle 第二个区间的开始位置
* @param right 第二个区间段结束的位置
*/
private static void merge(int[] R,int[] tempR,int left,int middle,int right){
int leftEnd=middle-1; //左指针尾
int rightStart=middle;//右指针
int tempIndex=left;//临时数组的小标
int tempLength=right-left+1;//数组合并后的length长度
//先循环两个区间段都没有结束的情况
while((left<=leftEnd)&&(rightStart<=right)){
if(R[left]<R[rightStart])
tempR[tempIndex++]=R[left++];
else
tempR[tempIndex++]=R[rightStart++];
}
while(left<=leftEnd)//如果还没完继续加入临时数组中
tempR[tempIndex++]=R[left++];
while(rightStart<=right)
tempR[tempIndex++]=R[rightStart++];
//交换数据
for(int i=0;i<tempLength;i++){
R[right]=tempR[right];
right--;
}
}
/**
* 基数排序算法
* @param number
* @param d
*/
public static void jiShuSort(int[]number,int d){//d表示最大的数有多少位
int k = 0;
int n = 1;
int m = 1; //控制键值排序依据在哪一位
int[][]temp = new int[10][number.length]; //数组的第一维表示可能的余数0-9
int[]order = new int[10]; //数组orderp[i]用来表示该位是i的数的个数
while(m <= d)
{
for(int i = 0; i < number.length; i++)
{
int lsd = ((number[i] / n) % 10);
temp[lsd][order[lsd]] = number[i];
order[lsd]++;
}
for(int i = 0; i < 10; i++)
{
if(order[i] != 0)
for(int j = 0; j < order[i]; j++)
{
number[k] = temp[i][j];
k++;
}
order[i] = 0;
}
n *= 10;
k = 0;
m++;
}
}
}