今天是学习的算法的第三天内容为归并排序,今天难度比昨天更为上升,坚持就是胜利。
归并排序:
思想:
现将一个个数组分为两个子数组。然后递归的将数组进行排序,并将已排序的子数组合并成一个大的有序数组,直到合并为1个完整的数组。
事例:
有个数组[2,7,3,9,1,6,4,5]
先将数组分为两部分也就是:
[2,7,3,9]和[1,6,4,5]
然后再进行分割。
分为[2,7],[3,9],[1,6],[4,5]。
然后再不断进行分割。
接下来,归并排序开始合并这些有序的子数组。它总是从最小的子数组(即长度为1的数组)开始,逐步向上合并成更大的有序数组。在这个例子中,合并过程将如下进行:
- 合并
[2]
和[7]
得到[2, 7]
- 合并
[3]
和[9]
得到[3, 9]
- 合并
[1]
和[6]
得到[1, 6]
- 合并
[4]
和[5]
得到[4, 5]
然后,继续合并这些长度为2的有序数组:
- 合并
[2, 7]
和[3, 9]
得到[2, 3, 7, 9]
- 合并
[1, 6]
和[4, 5]
得到[1, 4, 5, 6]
最后,合并 [2, 3, 7, 9]
和 [1, 4, 5, 6]
得到完全排序的数组 [1, 2, 3, 4, 5, 6, 7, 9]
。
python代码如下:
n=int(input())#多少数字
a=list(map(int,input().split()))
def merge(leftlist,rightlist):
newlist = []
while len(leftlist)!=0 and len(rightlist)!=0:
if leftlist[0]<rightlist[0]:
newlist.append(leftlist.pop(0))#哪个数字更小就把哪个数字放入新列表当中。
else:
newlist.append(rightlist.pop(0))
newlist.extend(leftlist)#两个列表当中必定有一个列表为空列表一个列表只剩一个数字。
newlist.extend(rightlist)
return newlist
def mergesort(a):
if len(a)<2:
return a
mid=len(a)//2
leftlist=mergesort(a[:mid])
rightlist=mergesort(a[mid:])
return merge(leftlist,rightlist)#不断地递归
print(mergesort(a))
注意归并排序有个小细节
print(mergesort(a))
//改成
mergesort(a)
print(a)
这样的结果是不一样的,归并排序不是一个原地排序算法。它使用额外的空间来创建和合并子列表。因此归并排序不是在原来的列表中修改的,他是新建了一个列表,也就是上面代码的newlist。
所以直接输出print(a)的话结果是错误的。
c++代码如下:
using namespace std;
const int N = 1e5 + 1;
int a[N];
// 合并两个已排序的部分到newlist数组,然后复制回a数组
void merge(int a[], int left, int mid, int right) {
int n1 = mid - left + 1;
int n2 = right - mid;
int L[n1], R[n2], *newlist = new int[n1 + n2]; // 创建动态数组以避免局部变量作用域问题
// 拷贝数据到临时数组
for (int i = 0; i < n1; i++)
L[i] = a[left + i];
for (int j = 0; j < n2; j++)
R[j] = a[mid + 1 + j];
// 合并临时数组到newlist
int i = 0, j = 0, k = 0;
while (i < n1 && j < n2) {
if (L[i] <= R[j]) {
newlist[k++] = L[i++];
} else {
newlist[k++] = R[j++];
}
}
// 拷贝剩余的L或R中的元素
while (i < n1) {
newlist[k++] = L[i++];
}
while (j < n2) {
newlist[k++] = R[j++];
}
// 复制newlist到a数组
for (int i = 0; i < n1 + n2; i++) {
a[left + i] = newlist[i];
}
}
// 归并排序的主函数
void mergeSort(int a[], int left, int right) {
if (left < right) {
int mid = left + (right - left) / 2;
mergeSort(a, left, mid);
mergeSort(a, mid + 1, right);
merge(a, left, mid, right);
}
}
int main() {
int n;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> a[i];
}
mergeSort(a, 0, n - 1);
for (int i = 0; i < n; i++) {
cout << a[i] << " ";
}
return 0;
}
c++的归并排序有多种写法,这里只提供一种。
OK今天的算法内容就到这了,今天是学算法的第三天天,算法最重要的内容是要多练,你的放弃可能会成就更多的人,欢迎评论区打卡,我们明天再见。