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;
}
}
}
}
一些盲点:归并排序究竟在外部排序怎么用?外部排序哪些算法?