实现折半插入排序法,折半插入排序是对插入排序算法的一种改进,插入排序在列表较低的一端维护一个有序的子列表,并逐个将每个新元素“插入”这个子列表中,由于前半部分为已排好序的列表,因此不用按顺序依次寻找插入点,可以采用折半查找的方法来加快寻找插入点的速度。python代码
时间: 2024-11-28 08:25:40 浏览: 41
在Python中,你可以通过以下步骤实现折半插入排序算法:
首先,我们需要一个折半查找函数,它能在有序数组中快速找到插入位置:
```python
def binary_search(arr, target):
low, high = 0, len(arr) - 1
while low <= high:
mid = (low + high) // 2
if arr[mid] < target:
low = mid + 1
else:
high = mid - 1
return low
```
然后,我们编写折半插入排序的主要部分:
```python
def insertion_sort_half_sorted(arr):
for i in range(1, len(arr)):
key = arr[i]
# 使用二分查找找到正确的位置
j = binary_search(arr[:i], key)
# 将元素插入到正确位置
for k in range(i, j, -1):
arr[k] = arr[k - 1]
arr[j] = key
```
这个函数从第二个元素开始遍历,对每一个元素,先使用二分查找找到应该插入的位置,然后将该元素移动到正确的位置。
相关问题
折半插入排序法C语言
折半插入排序(也称为二分插入排序)是一种改进版的插入排序算法,它适用于已经部分有序的数据集,效率相对较高。在C语言中,其基本思想是将数组分为已排序区和未排序区,每次从未排序区找到一个元素,通过比较将其插入到已排序区的适当位置,这个过程是通过查找插入点的方式来实现的。
以下是简单的C语言实现步骤:
1. 初始化:假设数组的第一个元素已经被视为已排序,索引从`i = 1`开始。
2. 当`i < 数组长度`时,执行循环:
a. 计算中间元素的位置 `mid = (i + (array_length - i)) / 2`。
b. 如果中间元素大于等于待插入的元素,那么更新中间元素的下标为`mid - 1`,因为已知右侧都是比它小的元素。
c. 比较中间元素和待插入元素,如果待插入元素小于中间元素,就继续在左半部分进行插入操作,否则在右半部分。
d. 递归地重复上述步骤,直到找到合适的插入位置。
4. 插入待插入元素到找到的位置,并移动右侧的元素以保持排序。
以下是简化版的C语言代码示例:
```c
void insertion_sort_half(int arr[], int length) {
for (int i = 1; i < length; ++i) {
int key = arr[i];
int j;
for (j = i; j > 0 && arr[j - 1] > key; j = j / 2) { // 取前半部分最接近的值
arr[j] = arr[j - 1]; // 将较大的移到右边
}
arr[j] = key; // 插入键值
}
}
```
c语言折半插入排序法双链表
折半插入排序是一种高效的排序算法,而双向链表则是一种支持双向遍历的数据结构。下面是使用折半插入排序法对双链表进行排序的示例代码:
```c
#include <stdio.h>
#include <stdlib.h>
// 定义双向链表节点
typedef struct Node {
int data;
struct Node* prev;
struct Node* next;
} Node;
// 定义双向链表
typedef struct List {
Node* head;
Node* tail;
} List;
// 初始化双向链表
List* initList() {
List* list = (List*)malloc(sizeof(List));
list->head = NULL;
list->tail = NULL;
return list;
}
// 创建新节点
Node* createNode(int data) {
Node* node = (Node*)malloc(sizeof(Node));
node->data = data;
node->prev = NULL;
node->next = NULL;
return node;
}
// 在链表尾部插入新节点
void insertNode(List* list, Node* node) {
if (list->head == NULL) {
list->head = node;
list->tail = node;
} else {
node->prev = list->tail;
list->tail->next = node;
list->tail = node;
}
}
// 折半插入排序
void insertionSort(List* list) {
Node* current = list->head->next;
while (current != NULL) {
Node *p = list->head, *q = current->prev;
while (p != current && p->data <= current->data) {
p = p->next;
}
while (q != p) {
q->next->data = q->data;
q = q->prev;
}
p->data = current->data;
current = current->next;
}
}
// 打印链表
void printList(List* list) {
Node* current = list->head;
while (current != NULL) {
printf("%d ", current->data);
current = current->next;
}
printf("\n");
}
int main() {
List* list = initList();
insertNode(list, createNode(5));
insertNode(list, createNode(3));
insertNode(list, createNode(8));
insertNode(list, createNode(1));
insertNode(list, createNode(2));
printf("Original list: ");
printList(list);
insertionSort(list);
printf("Sorted list: ");
printList(list);
return 0;
}
```
这段代码中,我们首先定义了一个双向链表节点 `Node` 和一个双向链表 `List`。然后,我们实现了双向链表的初始化、创建新节点、在链表尾部插入新节点、折半插入排序、打印链表等功能。在 `insertionSort` 函数中,我们使用了折半插入排序的算法对双向链表进行排序。最后,我们调用 `main` 函数来测试我们的代码。
阅读全文