二分插入排序
二分法插入排序,简称二分排序,是在插入第i个元素时,对前面的0~i-1元素进行折半,先跟他们中间的那个元素比,如果小,则对前半再进行折半,否则对后半进行折半,直到left<right,然后再把第i个元素前1位与目标位置之间的所有元素后移,再把第i个元素放在目标位置上。
算法思想
二分法没有排序,只有查找。所以当找到要插入的位置时。移动必须从最后一个记录开始,向后移动一位,再移动倒数第2位,直到要插入的位置的记录移后一位。
1、查找
二分法查找插入位置
如果R<R[m]成立,那右指针就要向左移动中间指针一位,否则,左指针要向右移动中间指针一位。反复查找,直到左指针大于右指针时停止。
2、后移
有点迷惑,什么时候需要后移呢?有哪些记录需要移动呢?
虽然我们很清楚的知道,我们需要后移那些排序码大于R的记录,但难免会问自己这样几个问题。其实它相当于需要移动从i-1到左指针的记录。
3、插入
由1中得到的左指针其实就是元素要插入的位置。
Java实现
/**
* 二分插入排序
*
* @param nums
* @return
*/
public static int[] binaryInsertSort(int[] nums){
if(null == nums || nums.length == 0){
System.out.println("输入的数组为空!");
return null;
}
for (int i = 1; i < nums.length; i++) {
int temp = nums[i];
int low = 0, high = i - 1;
int mid = -1;
while (low <= high) {
mid = low + (high - low) / 2;
if (nums[mid] > temp) {
high = mid - 1;
} else { // 元素相同时,也插入在后面的位置
low = mid + 1;
}
}
for(int j = i - 1; j >= low; j--) {
nums[j + 1] = nums[j];
}
nums[low] = temp;
}
return nums;
}
单链表直接插入排序
算法描述
单链表插入排序和数组插入排序的不同:数组插入排序是从排好序的部分的最后一个节点往前找,找到第一个比它小的数,然后插到其后面;而单链表只能从前往后遍历,找到第一个比当前节点大的值结束,因此在遍历已经排好序的链表部分的时候,需要两个指针,一个指针用于往前遍历(该指针假设为遍历指针),一个指针用于记录遍历指针指向的当前节点的前一个节点(该指针假设为遍历指针),这样当遍历指针找到第一个比待插入节点的值大的节点的时候,就可以将待插入节点插入到记录指针的后面。(之所以使用两个指针,是因为单链表不能反指)
插入排序分两种情况,一种是当前节点的值比已经排好序的尾节点的值大,则直接将当前节点挂在已排序的节点即可;一种是当前节点值比已经排好序的尾节点的值小,则需将已排好序的链表部分从头到尾遍历,找到第一个比当前节点值大的节点,插入到其前面即可。因为可能待插入的节点可能在第一个节点的前面,因此另外创建一个头结点,指向已经排好序的链表的第一个节点。这样可以每次插入新的节点的时候,将上面所提到的记录节点初始化为新创建的头结点,这样便于在第一个节点前面插入新节点。
Java实现
单链表的实现在此不赘述,有想了解的朋友可以查看https://blog.youkuaiyun.com/u014229347/article/details/88966409
/**
* <p>@filename SingleLinkedListInsertSort</p>
* <p>
* <p>@description 单链表直接插入排序</p>
*
* @author Java猿人一枚
* @version 1.0
* @since 2019/4/1 16:42
**/
public class SingleLinkedListInsertSort {
public static void main(String[] args) {
int[] nums = new int[]{100,34,52,6,8,78,95};
SingleLinkedList<Integer> singleLinkedList = new SingleLinkedList<>();
for (int i = 0; i < nums.length; i++) {
singleLinkedList.addNode(nums[i], i);
}
System.out.print("排序前:");
singleLinkedList.print();
System.out.println();
singleLinkedList = singleLinkedListInsertSort(singleLinkedList);
System.out.print("排序后:");
singleLinkedList.print();
}
/**
* 单链表插入排序
*
* @param singleLinkedList
* @return
*/
public static SingleLinkedList<Integer> singleLinkedListInsertSort(SingleLinkedList<Integer> singleLinkedList){
SingleLinkedList.Node<Integer> head = singleLinkedList.getHead();
if(head == null || head.next == null){
return singleLinkedList;
}else{
SingleLinkedList<Integer> newSingleLinkedList = new SingleLinkedList<>();
newSingleLinkedList.addHead(head.value);
while(head.next != null){
head = head.next;
SingleLinkedList.Node<Integer> newHead = newSingleLinkedList.getHead();
for (int i = 0; i < newSingleLinkedList.size(); i++){
if(head.value < newHead.value){
newSingleLinkedList.addNode(head.value, i);
newSingleLinkedList.print();
System.out.println();
break;
}else{
newHead = newHead.next;
}
}
}
singleLinkedList = newSingleLinkedList;
}
return singleLinkedList;
}
}
以上代码均为个人实现,有问题欢迎一起交流探讨!