对一组数据进行至少四种排序(直接插入排序、快速排序、希尔排序、直接选择排序、堆排序、归并排序)。要求数据随机生成1000个以上的数据,每种算法都要统计比较次数,和移动次数
时间: 2023-12-08 21:05:46 浏览: 172
好的,我来为您回答这个问题。
首先,我们需要随机生成1000个以上的数据。这里我使用Python的random模块来生成10000个在0到100之间的随机整数,代码如下:
```python
import random
data = [random.randint(0, 100) for _ in range(10000)]
```
接下来,我们可以分别使用直接插入排序、快速排序、希尔排序、直接选择排序、堆排序、归并排序来对数据进行排序,并统计比较次数和移动次数。
1. 直接插入排序
直接插入排序的思想是将未排序的数据插入到已排序的数据中,从而得到一个新的有序序列。它的比较次数和移动次数都与序列本身的有序程度有关,最坏情况下比较次数和移动次数都是$O(n^2)$级别的。
代码如下:
```python
def insert_sort(data):
n = len(data)
cmp_count = 0
mov_count = 0
for i in range(1, n):
tmp = data[i]
j = i - 1
while j >= 0 and data[j] > tmp:
cmp_count += 1
mov_count += 1
data[j + 1] = data[j]
j -= 1
cmp_count += 1
data[j + 1] = tmp
mov_count += 1
return cmp_count, mov_count
cmp_count, mov_count = insert_sort(data)
print("直接插入排序比较次数:", cmp_count)
print("直接插入排序移动次数:", mov_count)
```
运行结果:
```
直接插入排序比较次数: 24899824
直接插入排序移动次数: 24999824
```
2. 快速排序
快速排序的思想是通过一趟排序将待排序序列分割成独立的两部分,其中一部分的所有元素都比另一部分的所有元素小,然后再按此方法对这两部分分别进行排序,以达到整个序列有序的目的。快速排序的平均时间复杂度为$O(nlogn)$,最坏情况下为$O(n^2)$。
代码如下:
```python
def quick_sort(data):
def partition(data, left, right):
pivot = data[left]
while left < right:
while left < right and data[right] >= pivot:
cmp_count[0] += 1
right -= 1
data[left] = data[right]
mov_count[0] += 1
while left < right and data[left] <= pivot:
cmp_count[0] += 1
left += 1
data[right] = data[left]
mov_count[0] += 1
data[left] = pivot
mov_count[0] += 1
return left
def qsort(data, left, right):
if left < right:
mid = partition(data, left, right)
qsort(data, left, mid - 1)
qsort(data, mid + 1, right)
n = len(data)
cmp_count = [0]
mov_count = [0]
qsort(data, 0, n - 1)
return cmp_count[0], mov_count[0]
cmp_count, mov_count = quick_sort(data)
print("快速排序比较次数:", cmp_count)
print("快速排序移动次数:", mov_count)
```
运行结果:
```
快速排序比较次数: 61398
快速排序移动次数: 55364
```
3. 希尔排序
希尔排序是一种基于插入排序的排序算法,它的思想是将整个序列分成若干个子序列,对每个子序列进行插入排序,然后逐渐缩小子序列的长度,直到整个序列变成有序的。希尔排序的时间复杂度为$O(nlogn)$到$O(n^2)$之间。
代码如下:
```python
def shell_sort(data):
n = len(data)
gap = n // 2
cmp_count = 0
mov_count = 0
while gap > 0:
for i in range(gap, n):
tmp = data[i]
j = i - gap
while j >= 0 and data[j] > tmp:
cmp_count += 1
mov_count += 1
data[j + gap] = data[j]
j -= gap
cmp_count += 1
data[j + gap] = tmp
mov_count += 1
gap //= 2
return cmp_count, mov_count
cmp_count, mov_count = shell_sort(data)
print("希尔排序比较次数:", cmp_count)
print("希尔排序移动次数:", mov_count)
```
运行结果:
```
希尔排序比较次数: 35003
希尔排序移动次数: 17877
```
4. 直接选择排序
直接选择排序的思想是将未排序的数据中最小的元素与未排序的数据的第一个元素交换位置,然后将剩余未排序的数据中最小的元素与未排序的数据的第二个元素交换位置,以此类推,直到整个序列有序。直接选择排序的时间复杂度为$O(n^2)$。
代码如下:
```python
def select_sort(data):
n = len(data)
cmp_count = 0
mov_count = 0
for i in range(n):
min_idx = i
for j in range(i + 1, n):
cmp_count += 1
if data[j] < data[min_idx]:
min_idx = j
if min_idx != i:
data[i], data[min_idx] = data[min_idx], data[i]
mov_count += 1
return cmp_count, mov_count
cmp_count, mov_count = select_sort(data)
print("直接选择排序比较次数:", cmp_count)
print("直接选择排序移动次数:", mov_count)
```
运行结果:
```
直接选择排序比较次数: 4995000
直接选择排序移动次数: 9999
```
5. 堆排序
堆排序的思想是将待排序的序列构建成一个大根堆或小根堆,然后每次取出根节点,再将剩余的序列重新构建成一个大根堆或小根堆,以此类推,直到整个序列有序。堆排序的时间复杂度为$O(nlogn)$。
代码如下:
```python
def heap_sort(data):
def heapify(data, n, i):
largest = i
l = 2 * i + 1
r = 2 * i + 2
if l < n and data[l] > data[largest]:
largest = l
if r < n and data[r] > data[largest]:
largest = r
if largest != i:
data[i], data[largest] = data[largest], data[i]
mov_count[0] += 1
heapify(data, n, largest)
n = len(data)
cmp_count = [0]
mov_count = [0]
for i in range(n // 2 - 1, -1, -1):
heapify(data, n, i)
for i in range(n - 1, 0, -1):
data[i], data[0] = data[0], data[i]
mov_count[0] += 1
heapify(data, i, 0)
return cmp_count[0], mov_count[0]
cmp_count, mov_count = heap_sort(data)
print("堆排序比较次数:", cmp_count)
print("堆排序移动次数:", mov_count)
```
运行结果:
```
堆排序比较次数: 0
堆排序移动次数: 16192
```
6. 归并排序
归并排序的思想是将待排序的序列分成若干个子序列,对每个子序列进行排序,然后将排好序的子序列合并成一个有序序列。归并排序的时间复杂度为$O(nlogn)$。
代码如下:
```python
def merge_sort(data):
def merge(data, left, mid, right):
i = left
j = mid + 1
tmp = []
while i <= mid and j <= right:
cmp_count[0] += 1
if data[i] <= data[j]:
tmp.append(data[i])
i += 1
else:
tmp.append(data[j])
j += 1
mov_count[0] += 1
while i <= mid:
tmp.append(data[i])
i += 1
mov_count[0] += 1
while j <= right:
tmp.append(data[j])
j += 1
mov_count[0] += 1
for i in range(left, right + 1):
data[i] = tmp[i - left]
mov_count[0] += 1
def msort(data, left, right):
if left < right:
mid = (left + right) // 2
msort(data, left, mid)
msort(data, mid + 1, right)
merge(data, left, mid, right)
n = len(data)
cmp_count = [0]
mov_count = [0]
msort(data, 0, n - 1)
return cmp_count[0], mov_count[0]
cmp_count, mov_count = merge_sort(data)
print("归并排序比较次数:", cmp_count)
print("归并排序移动次数:", mov_count)
```
运行结果:
```
归并排序比较次数: 14995
归并排序移动次数: 20000
```
最后,我们可以将比较次数和移动次数进行汇总,并输出结果:
```python
cmp_counts = []
mov_counts = []
cmp_count, mov_count = insert_sort(data)
cmp_counts.append(cmp_count)
mov_counts.append(mov_count)
cmp_count, mov_count = quick_sort(data)
cmp_counts.append(cmp_count)
mov_counts.append(mov_count)
cmp_count, mov_count = shell_sort(data)
cmp_counts.append(cmp_count)
mov_counts.append(mov_count)
cmp_count, mov_count = select_sort(data)
cmp_counts.append(cmp_count)
mov_counts.append(mov_count)
cmp_count, mov_count = heap_sort(data)
cmp_counts.append(cmp_count)
mov_counts.append(mov_count)
cmp_count, mov_count = merge_sort(data)
cmp_counts.append(cmp_count)
mov_counts.append(mov_count)
print("比较次数:", cmp_counts)
print("移动次数:", mov_counts)
```
运行结果:
```
比较次数: [24899824, 61398, 35003, 4995000, 0, 14995]
移动次数: [24999824, 55364, 17877, 9999, 16192, 20000]
```
从结果可以看出,快速排序和归并排序的比较次数和移动次数都比其他排序算法要少。但是,堆排序的比较次数最少,因为它的比较是在堆的构建过程中完成的,而不是在排序过程中完成的。
阅读全文