首先定义一个交换函数
static void swap(Object[] obj,int i,int j)
{
Object temp;
temp = obj[i];
obj[i] = obj[j];
obj[j] = temp;
}
假设排序后实现的都是关键码的升序
1、插入排序
算法思想:逐个处理待排序的记录,每个新纪录与前面以排序的子纪录作比较。叫它插入到子序列中正确的位置
下面是代码实现
static void insSort(Object[] obj,int n)
{
for(int i = 1;i < n;i++)
{
for(int j = i;(j > 0)&&((int)obj[j] < (int)obj[j - 1]);j--)
{
swap(obj,j,j - 1);
}
}
}
2、冒泡排序
算法思想:用一个简单的双重循环。内部循环第一次从记录的底部比较到顶部,每次比较都为相邻关键码,如果低序号的关键码值比高序号的关键码值大,就交换其位置
下面是代码实现
static void bubSort(Object[] obj,int n)
{
for(int i = 0;i < n - 1;i++)
{
for(int j = n - 1;j > i;j--)
{
if((int)obj[j] < (int)obj[j - 1])
{
swap(obj,j,j - 1);
}
}
}
}
3、选择排序
算法思想:第i次是选择记录中第i小的记录,并将该记录放到数组的第i个位置。
代码实现
static void selSort(Object[] obj,int n)
{
for(int i = 0;i < n - 1;i++)
{
int lowIndex = i;
for(int j = n - 1;j > i;j--)
{
if((int)obj[j] < (int)obj[lowIndex])
{
lowIndex = j;
}
}
swap(obj,i,lowIndex);
}
}
4、shell排序(缩小增量排序)
算法思想:利用插入排序对基本有序的记录排序时间少的优点,将记录分成子序列,对每个子序列进行插入排序,然后合并子序列
代码实现
static void insSort(Object[] obj,int n,int incr)//用于shell排序的插入排序
{
for(int i = incr;i < n;i += incr)
{
for(int j = i;(j >= incr) && ((int)obj[j] < (int)obj[j - incr]);j -= incr)
{
swap(obj,j,j - incr);
}
}
}
static void shellSort(Object[] obj,int n)//shell排序
{
for(int i = n/2;i > 2;i /= 2)
{
for(int j = 0;j < i;j++)
{
insSort(obj,n-j,i);
}
}
insSort(obj,n,1);
}
5、快速排序
算法思想:“分治法”,首先选定一个轴值,然后将记录中小于轴值的值放在轴值左边,大于轴值的值放在轴值右边。对轴值两边的记录同样可以使用快速排序
代码实现
static int findPivot(Object[] obj,int i,int j)//快速排序中找到轴值的位置,即中点
{
return (i + j)/2;
}
static int partition(Object[] obj,int l,int r,Object pivot)//将记录移动到合适的分组
{
do
{
while((int)obj[++l] > (int)pivot);
while((r != 0) && ((int)obj[--r] < (int)pivot));
swap(obj,l,r);
}while(l < r);
swap(obj,l,r);
return l;
}
static void qSort(Object[] obj,int i,int j)//快速排序
{
if(j <= i)
return;
int pivotIndex = findPivot(obj,i,j);
swap(obj,pivotIndex,j);
int k = partition(obj,i - 1,j,obj[j]);
swap(obj,k,j);
qSort(obj,j,k - 1);
qSort(obj,k + 1,j);
}
6、归并排序
算法思想:将序列分成两个长度相等的子序列,为每一个子序列排序,然后再将它们合并成一个序列
代码实现
static void mergeSort(Object[] obj,Object[] temp,int left,int right)
{
int mid = (left + right)/2;
if(left == right)
return;
mergeSort(obj,temp,left,mid);
mergeSort(obj,temp,mid+1,right);
for(int i = left;i <= right;i++)
temp[i] = obj[i];
int i1 = left;
int i2 = mid + 1;
for(int curr = left;curr <= right;curr++)
{
if(i1 == mid + 1)
obj[curr] = temp[i2++];
else if(i2 > right)
obj[curr] = temp[i1++];
else if((int)temp[i1] < (int)temp[i2])
obj[curr] = temp[i1++];
else
obj[curr] = temp[i2++];
}
}
7、堆排序
算法思想:利用堆的特征,依次取出堆顶,知道堆为空,取出来的记录就是已排序的记录
实现代码(基于已写好的最大值堆)
static Object[] heapSort(Object[] obj,int n)//堆排序
{
MaxHeap mh = new MaxHeap(obj,n,n);
for(int i = 0;i < n;i++)
{
obj[n-i-1] = mh.removeMax();
}
return obj;
}
算法思想:B[A[i]] = A[i],用关键码来确定一个记录在排序中的最终位置。
这个排序算法局限性太大,就不实现了
9、基数排序
算法思想:基数排序是分配排序的一种扩展,也可以称为桶式排序。基本思想就是将记录放入桶中,然后借助其他的排序算法对桶中记录进行排序
代码实现
static void radixSort(Object[] obj,Object[] temp,int n,int k,int r,int[] cnt)//基数排序
{
int j;
for(int i = 0,rtok = 1;i < k;i++,rtok *= r)
{
for(j = 0;j < r;j++)
cnt[j] = 0;
for(j = 0;j < n;j++)
{
int l = ((int)obj[j]/rtok)%r;
cnt[l]++;
}
for(j = 1;j < r;j++)
cnt[j] = cnt[j - 1] + cnt[j];
for(j = n -1;j >= 0;j--)
temp[--cnt[((int)obj[j] / rtok) % r]] = obj[j];
for(j = 0;j < n;j++)
obj[j] = temp[j];
}
}
解释一下基数排序,因为他看起来好像有点难以理解
先看六个参数,obj为待排序数组,temp是临时数组,n为待排序数组长度,k为关键码的最长为数,k多大,则比较多少次,r为辅助数组的长度,cnt为记录数组,记录每个盒子被分配多少关键码。
内层循环:第一个是初始化cnt,第二个是记录每个盒子被分配的关键码数目,第三个循环用于统计关键码数目,以把它们分配给临时数组,第四个循环是把他们分配个临时数组,第五个循环是把记录复制回原数组。进过第一轮排序后,关键码已在最右有序