一、 关系与复杂度
1. 关系与复杂度
2. 算法复杂度
二、直接插入排序
1. 原理:
将一个记录插入到已排序好的有序表中,从而得到一个新的、记录数+1的有序表。
2. Java代码实现
//默认原始数组sort为升序排列,num为待插入数
public static int[] insertSort(int sort[],int num){
int[] newSort = new int[sort.length+1];
int id = 0;
for(int i=0;i<sort.length;i++){
if(sort[i]>num){
id=i;
break;
}
}
for(int i=0;i<sort.length+1;i++){
if(i==id){
newSort[i]=num;
}else if(i< id){
newSort[i]=sort[i];
}else{
newSort[i]=sort[i-1];
}
}
return newSort;
}
三、希尔(shell)排序
1. 简介
希尔排序是插入排序的一种高效率的实现,也叫缩小增量排序。简单的插入排序中,如果待排序列是正序时,时间复杂度是O(n),如果序列是基本有序的,使用直接插入排序效率就非常高。希尔排序就利用了这个特点。
2. 基本思想
先将整个待排记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录基本有序时再对全体记录进行一次直接插入排序。
3. java代码实现
public static int[] shellSort(int sort[]){
int gap = sort.length/2;
while(gap >= 1){
for(int i=gap;i<sort.length;i++){
int j=i;
while(j>=gap&&sort[j]<sort[j-gap]){
int temp = sort[j];
sort[j] = sort[j-gap];
sort[j-gap] = temp;
j-=gap;
}
}
gap/=2;
}
return sort;
}
四、简单选择排序
1. 算法思想
设所排序序列的记录个数为n。i取1,2,…,n-1,从所有n-i+1个记录(Ri,Ri+1,…,Rn)中找出排序码最小的记录,与第i个记录交换。执行n-1趟 后就完成了记录序列的排序。
2. java代码实现
public static int[] selectSort(int sort[]){
for(int i=0;i<sort.length;i++){
int min = sort[i];
int minNum = i;
for(int j=1;j<sort.length;j++){
if(min>sort[j]){
min = sort[j];
minNum = j;
}
}
int temp = sort[i];
sort[i] = sort[minNum];
sort[minNum] = temp;
}
return sort;
}
五、堆排序
1. 堆的概念
本质是一种数组对象。特别重要的一点性质:任意的叶子节点小于(或大于)它所有的父节点。对此,又分为大顶堆和小顶堆,大顶堆要求节点的元素都要大于其孩子,小顶堆要求节点元素都小于其左右孩子,两者对左右孩子的大小关系不做任何要求。
利用堆排序,就是基于大顶堆或者小顶堆的一种排序方法。下面,我们通过大顶堆来实现。
2. 基本思想
-
首先将序列构建称为大顶堆;
(这样满足了大顶堆那条性质:位于根节点的元素一定是当前序列的最大值) -
取出当前大顶堆的根节点,将其与序列末尾元素进行交换;
(此时:序列末尾的元素为已排序的最大值;由于交换了元素,当前位于根节点的堆并不一定满足大顶堆的性质) -
对交换后的n-1个序列元素进行调整,使其满足大顶堆的性质;
3. java代码实现
public static void headSort(int[] list) {
//构造初始堆,从第一个非叶子节点开始调整,左右孩子节点中较大的交换到父节点中
for (int i = (list.length) / 2 - 1; i >= 0; i--) {
headAdjust(list, list.length, i);
}
//排序,将最大的节点放在堆尾,然后从根节点重新调整
for (int i = list.length - 1; i >= 1; i--) {
int temp = list[0];
list[0] = list[i];
list[i] = temp;
headAdjust(list, i, 0);
}
private static void headAdjust(int[] list, int len, int i) {
int k = i, temp = list[i], index = 2 * k + 1;
while (index < len) {
if (index + 1 < len) {
if (list[index] < list[index + 1]) {
index = index + 1;
}
}
if (list[index] > temp) {
list[k] = list[index];
k = index;
index = 2 * k + 1;
} else {
break;
}
}
list[k] = temp;
}
六、 冒泡排序
1. 算法思想
- 将序列当中的左右元素,依次比较,保证右边的元素始终大于左边的元素;
- 对序列当中剩下的n-1个元素再次执行步骤1。
- 对于长度为n的序列,一共需要执行n-1轮比较 。
2. java代码实现
public static int[] bubbleSort(int sort[]){
for(int i=0;i<sort.length-1;i++){
for(int j =0;j<sort.length-i-1){
if(sort[j]>sort[j+1]){
int temp = sort[j];
sort[j]=sort[j+1];
sort[j+1]= temp;
}
}
}
return sort;
}
七、 快速排序
1. 算法原理
通过一趟排序将序列分成左右两部分,其中左半部分的的值均比右半部分的值小,然后再分别对左右部分的记录进行排序,直到整个序列有序。
2. java代码实现
public static int[] quickSort(int[] sort,int low,int high){
if(low>high){
return;
}
int temp = arr[low];
int i = low;
int j = high;
while (i<j) {
//先看右边,依次往左递减
while (temp<=arr[j]&&i<j) {
j--;
}
//再看左边,依次往右递增
while (temp>=arr[i]&&i<j) {
i++;
}
//如果满足条件则交换
if (i<j) {
t = arr[j];
arr[j] = arr[i];
arr[i] = t;
}
}
//最后将基准为与i和j相等位置的数字交换
arr[low] = arr[i];
arr[i] = temp;
//递归调用左半数组
quickSort(arr, low, j-1);
//递归调用右半数组
quickSort(arr, j+1, high);
}
八、归并排序
1. 算法原理
- 把有序表划分成元素个数尽量相等的两半
- 把两半元素分别排序
- 把两个有序表合并成一个
2. java代码实现
public static void merge(int[] arr,int low,int mid,int high,int[] tmp){
int i = 0;
int j = low,k = mid+1; //左边序列和右边序列起始索引
while(j <= mid && k <= high){
if(arr[j] < arr[k]){
tmp[i++] = arr[j++];
}else{
tmp[i++] = arr[k++];
}
}
//若左边序列还有剩余,则将其全部拷贝进tmp[]中
while(j <= mid){
tmp[i++] = arr[j++];
}
while(k <= high){
tmp[i++] = arr[k++];
}
for(int t=0;t<i;t++){
arr[low+t] = tmp[t];
}
}
public static void mergeSort(int[] arr,int low,int high,int[] tmp){
if(low<high){
int mid = (low+high)/2;
mergeSort(arr,low,mid,tmp); //对左边序列进行归并排序
mergeSort(arr,mid+1,high,tmp); //对右边序列进行归并排序
merge(arr,low,mid,high,tmp); //合并两个有序序列
}
}
九、基数排序
1. 算法思想
基数排序(RadixSort)是在桶排序的基础上发展而来的,两种排序都是分配排序的高级实现。分配排序(DistributiveSort)的基本思想:排序过程无须比较关键字,而是通过“分配”和“收集”过程来实现排序。
2.java代码
public static void radixSort(int[] array){
//首先确定排序的趟数;
int max=array[0];
for(int i=1;i<array.length;i++){
if(array[i]>max){
max=array[i];
}
}
int time=0;
//判断位数;
while(max>0){
max/=10;
time++;
}
//建立10个队列;
LinkQueue<Integer>[] queue=new LinkQueue[10];
for(int i=0;i<10;i++){
queue[i]=new LinkQueue<Integer>();
}
//进行time次分配和收集;
for(int i=0;i<time;i++){
//分配数组元素;
for(int j=0;j<array.length;j++){
//得到数字的第time+1位数;
queue[array[j]%(int)Math.pow(10, i+1)/(int)Math.pow(10, i)].enQueue(array[j]);
}
int count=0;//元素计数器;
//收集队列元素;
for(int k=0;k<10;k++){
while(queue[k].size()>0){
array[count]=(Integer) queue[k].deQueue().getElement();
count++;
}
}
}
}