分而治之是一种算法策略,其工作原理是将一个问题分解为两个或多个相同或相关类型的子问题,解决它们并添加子问题。 让我们说清楚。 在分而治之的技术中,我们需要将一个问题分解为多个子问题,然后递归求解,再将这些子问题组合在一起。 因此,我们可以假设,要遵循此策略,我们需要将 a 划分为几个部分,然后征服或求解这些部分,最后将它们组合在一起。 因此,我们可以轻松解决问题。
有许多遵循分而治之的算法。 例如递归二进制搜索,合并排序,快速排序,选择排序,Strassen矩阵乘法等。
我想做一个系列,其中我将讨论一些遵循分而治之策略的算法。
今天,我正在讨论合并排序。 合并排序是一种排序算法。 我们遵循的是分而治之的策略。 在合并排序中,我们将数组分为两部分,然后分别对它们进行排序,最后将它们组合起来。
首先,我们需要输入一个数组。 然后,我们将执行以下步骤:
步骤1:如果数组中的元素不超过一个,则说明该数组已经排序。
步骤2:然后,将数组的一半元素保留在名为left的新数组中,并合并排序后的数组。
步骤3:然后将数组的其他一半元素保留在正确的数组中,并合并对数组进行排序。
步骤4:最后合并两个合并的排序数组。
假设有一个包含八个元素的数组-8,3,2,9,7,1,5,4。 现在,我们将它们分为两部分。 然后,我们将按照前面的步骤进行操作。 通过查看这些图像,您可以得到清晰的解释。
要将这些步骤应用到程序中,首先需要一个合并排序程序,然后需要一个合并程序。 因此,让我们编写程序。
合并排序功能:
//ara is needed to merge sorted
//left is the index of first element
//right is the index of last element
void merge_sort (int ara[], int left, int right)
{
if(left >=right)
{
return;
}
//ara is divided into two parts
// one is from left to mid
// other is from mid+1 to right
int mid = left+(right-left)/2;
//applying merge sort from ara[left] to ara[mid]
merge_sort(ara,left,mid);
//applying merge sort from ara[mid+1] to ara[right]
merge_sort(ara,mid+1,right);
//finally merging them
merge(ara,left,mid,right);
}
然后我们需要做一个合并功能 。
void merge(int ara[],int left,int mid,int right)
{
int i;
int index_a, index_l, index_r;
int size_left, size_right;
size_left = mid - left + 1;
size_right = right - mid;
int L [size_left], R[size_right];
//copying from ara[left] to ara[mid]
for(i=0;i<size_left;i++)
{
L[i]=ara[left+i];
}
copying from ara[mid+1] to ara[right]
for(i=0;i<size_right;i++)
{
R[i]=ara[mid+1+i];
}
index_l = 0;
index_r = 0;
for(index_a = left;
index_l < size_left && index_r < size_right;
index_a++)
{
if(L[index_l]<R[index_r])
{
ara[index_a] = L[index_l];
index_l += 1;
}
else
{
ara[index_a] = R [index_r];
index_r += 1;
}
}
while (index_l < size_left)
{
ara[index_a] = L [index_l];
index_l += 1;
index_a += 1;
}
while (index_r < size_right)
{
ara[index_a] = R [index_r];
index_r += 1;
index_a += 1;
}
}
最终程序将是:
#include <iostream>
using namespace std;
void merge(int ara[],int left,int mid,int right);
//ara is needed to merge sorted
//left is the index of first element
//right is the index of last element
void merge_sort (int ara[], int left, int right)
{
if(left >=right)
{
return;
}
//ara is divided into two parts
// one is from left to mid
// other is from mid+1 to right
int mid = left+(right-left)/2;
//applying merge sort from ara[left] to ara[mid]
merge_sort(ara,left,mid);
//applying merge sort from ara[mid+1] to ara[right]
merge_sort(ara,mid+1,right);
//finally merging them
merge(ara,left,mid,right);
}
void merge(int ara[],int left,int mid,int right)
{
int i;
int index_a, index_l, index_r;
int size_left, size_right;
size_left = mid - left + 1;
size_right = right - mid;
int L [size_left], R[size_right];
//copying from ara[left] to ara[mid]
for(i=0;i<size_left;i++)
{
L[i]=ara[left+i];
}
copying from ara[mid+1] to ara[right]
for(i=0;i<size_right;i++)
{
R[i]=ara[mid+1+i];
}
index_l = 0;
index_r = 0;
for(index_a = left;
index_l < size_left && index_r < size_right;
index_a++)
{
if(L[index_l]<R[index_r])
{
ara[index_a] = L[index_l];
index_l += 1;
}
else
{
ara[index_a] = R [index_r];
index_r += 1;
}
}
while (index_l < size_left)
{
ara[index_a] = L [index_l];
index_l += 1;
index_a += 1;
}
while (index_r < size_right)
{
ara[index_a] = R [index_r];
index_r += 1;
index_a += 1;
}
}
int main()
{
int i, n = 7;
int ara[] = {8,3,2,9,7,1,5,4};
cout<<"After merge sorting:"<<endl;
merge_sort(ara,0,n);
for(i=0; i<=n; i++)
{
cout<<ara[i]<<endl;
}
return 0;
}
我们将获得如下输出:
合并排序的复杂度:
在这里,我们将数组分为两部分。 所以它的复杂性是
O(log n )。 但是我们也将它们合并了。 对于merge()函数,复杂度为O( n )。
因此,合并排序的复杂度为O((log n )x n )或O( n log n)。
编码愉快!
参考:
dimik的Bangla编程书籍改变了我的生活。
感谢Tamim Shahriar Subeen Vaiya :)。
From: https://hackernoon.com/divide-and-conquer-merge-sort-11c673470427