- package nuaa.ds;
- public class Sort<T>{
- //插入排序
- public void insertionSort(T[] t,Comparator<T> c){
- for(int i=1;i<t.length;i++){//确定有序序列
- T temp = t[i];//空出位置
- for(int j=i-1;j>=0;j--){//往前依次查找
- if(c.compare(temp, t[j])<0){
- t[j+1] = t[j];//前面的值大就往后移一位
- }else{
- t[j+1] = temp;//前面的值等于或者小于就插入
- break;
- }
- if(j==0){//循环到头了
- t[0] = temp;
- }
- }
- }
- }
- //希尔排序:思路类似插入排序
- public void shellSort(T[] t,Comparator<T> c){
- //除以2.2分割貌似是最佳的,最后分割必须为1
- for(int gap=t.length/2;gap>0;gap=(gap==2? 1:(int)(gap/2.2))){//加了个分割循环
- for(int i=gap;i<t.length;i+=gap){
- T temp = t[i];//当前的为坑
- for(int j=i-gap;j>=0;j-=gap){//0到i每个都比较,大的往后坑里填,小的就填值
- if(c.compare(t[j], temp)>0){
- t[j+gap]=t[j];
- }else{
- t[j+gap]=temp;
- break;
- }
- if(j==0){//循环到头了
- t[0] = temp;
- }
- }
- }
- }
- }
- //冒泡排序
- public void bubbleSort(T[] t,Comparator<T> c){
- for(int i=0;i<t.length;i++){//有length-1个元素要移动
- for(int j=0;j<t.length-i-1;j++){//从开始位置往后扫描
- if(c.compare(t[j], t[j+1])>0){//如果发现前面元素比后面大
- T temp=t[j];t[j]=t[j+1];t[j+1]=temp;//就互换
- }
- }
- }
- }
- //选择排序
- public void selectionSort(T[] t,Comparator<T> c){
- for(int i=0;i<t.length;i++){//确定位置当成最小值存放点
- int k=i;
- for(int j=i+1;j<t.length;j++){//从开始位置往后扫描
- if(c.compare(t[k], t[j])>0){//发现小值就记录下标
- k = j;
- }
- }
- T temp=t[i];t[i]=t[k];t[k]=temp;//存放入最小值
- }
- }
- //归并排序
- public void mergeSort(T[] t,Comparator<T> c){
- mergeSort(t,0,t.length-1,c);
- }
- private void mergeSort(T[] t,int low,int high,Comparator<T> c){
- if(low<high){//分割到一为止,
- int middle = (low+high)/2;
- mergeSort(t,low,middle,c);
- mergeSort(t,middle+1,high,c);
- //单个元素不需要排序,因此排序过程也在if语句里面
- T[] temp = (T[])new Object[high-low+1];
- int a = 0;//temp 的下标
- int lowIndex = low;//low到middle的索引,
- int highStart = middle+1;
- while((lowIndex<=middle)&&(high>=highStart)){//排序好的分割2列都有值
- if(c.compare(t[lowIndex], t[highStart])<=0){
- temp[a++] = t[lowIndex];
- lowIndex++;
- }else{
- temp[a++] = t[highStart];
- highStart++;
- }
- }
- while(lowIndex<=middle){//索引低的部分还有剩余项
- temp[a++] = t[lowIndex];
- lowIndex++;
- }
- while(high>=highStart){//索引高的部分还有剩余项
- temp[a++] = t[highStart];
- highStart++;
- }
- //重置temp的索引并拷贝回原数组
- for(a=0;a<temp.length;a++){
- t[low++] = temp[a];
- }
- }
- }
- //快速排序
- public void quickSort(T[] t,Comparator<T> c){
- quickSort(t,0,t.length-1,c);
- }
- private void quickSort(T[] t,int low,int high,Comparator<T> c){
- /*if(high-low==1){//分割到2个数快速排序有问题
- this.bubbleSort(t, c);
- return;
- if(c.compare(t[low], t[high])>0){
- T temp=t[low];t[low]=t[high];t[high]=temp;
- }
- return;
- }*/
- if(low<high){//一个数则不用排序
- int middle = (low+high)/2;
- T temp;//交换值的临时变量
- //三个if确定分割点并将分割点放在最后
- if(c.compare(t[low], t[middle])>0){
- temp = t[low];t[low] = t[middle];t[middle] = temp;
- }
- if(c.compare(t[low], t[high])>0){
- temp = t[low];t[low] = t[high];t[high] = temp;
- }
- if(c.compare(t[middle], t[high])<0){
- temp = t[middle];t[middle] = t[high];t[high] = temp;
- }
- int lowIndex = low;
- int highIndex = high;
- /**
- * 循环内只能放小于大于不能放等于,这样2个下标移动的时候才肯定会
- * 在最小和最大处停下来,而带来的副产品是下标的自增自减一定要放
- * 在循环内,不然会造成循环。
- */
- while(true){//等也要停下来防止越界
- while(c.compare(t[++lowIndex], t[high])<0)//lowIndex先开始因此
- //循环break后互换用lowIndex
- ;
- while(c.compare(t[--highIndex], t[high])>0)//自增自减放下面是死循环
- ; //加等号相等依然执行会越界
- if(lowIndex>=highIndex)
- break;
- temp=t[lowIndex];t[lowIndex]=t[highIndex];t[highIndex]=temp;
- }
- temp=t[lowIndex];t[lowIndex]=t[high];t[high]=temp;
- quickSort(t,low,lowIndex-1,c);
- quickSort(t,lowIndex+1,high,c);
- }
- }
- //堆排序
- public void heapSort(T[] t,Comparator<T> c){
- createHeap(t,t.length-1,c);//建立初堆
- for(int i=t.length-1;i>0;i--){ //每次最后和第一个元素互换,将最大元素
- T temp=t[i];t[i]=t[0];t[0]=temp; //沉底,第一个不需要所以for条件为>0
- reconstruct(t,0,i-1,c); //数组从0~i-1重新构造堆
- }
- }
- /**
- * 数组下标从0开始,二叉树从1开始,注意转换
- * @param t
- * @param lastIndex 数组的最后一个索引下标
- * @param c
- */
- private void createHeap(T[] t,int lastIndex,Comparator<T> c){
- for(int i=(lastIndex+1)/2;i>=1;i--)//i的值为二叉树的根下标,依次调整为堆
- reconstruct(t,i-1,t.length-1,c);//传递的为数组下标
- }
- /**
- *
- * @param t
- * @param firstIndex 数组第一个下标
- * @param lastIndex 数组最后一个下标
- * @param c
- */
- private void reconstruct(T[] t,int firstIndex,int lastIndex,Comparator<T> c){
- int first = firstIndex+1;//转化为二叉树
- int last = lastIndex+1;// 的下标
- int index = first*2;
- while(index<=last){//左子树存在
- if(index+1<=last&&c.compare(t[index], t[index-1])>0){//右子树存在且大
- if(c.compare(t[first-1],t[index])<0){//右子树大于根
- T temp=t[first-1];t[first-1]=t[index];t[index]=temp;
- first = index+1;
- index = 2*first;
- }else{
- break;
- }
- }else if(c.compare(t[first-1], t[index-1])<0){
- T temp=t[first-1];t[first-1]=t[index-1];t[index-1]=temp;
- first = index;
- index = first*2;
- }else{
- break;
- }
- }
- }
- }
一些盲点:归并排序究竟在外部排序怎么用?外部排序哪些算法?