写归并排序作业时候发现自己对递归有好多遗忘。
现对递归进行以下复习和总结:
- 归并排序利用的是分治的思想,“分治”即把复杂的问题分成简单的问题进行求解。
- 总的来说呢:分治是一种求解复杂问题的思想,而递归呢,就为其提供了求解的方法。
先说一下递归:
- 简单来说递归就是自己调用自己。递归关系就是实体自己和自己建立关系。
- 递归的条件:
(1)子问题与原问题需一致,且更简单。
(2)递归必须要有出口,不然就永远出不来了。
接下来我们用归并排序更加深入理解递归:
- 归并排序大致思想很简单:即先划分,再合并。
每次都一分为二,这样划分什么时候到头呢?
答:这样想,我们最终要得到的是一个排好序的大数组,子问题就是需要得到排好序的一个个小数组,小数组什么时候有序呢,当数组中就只有一个元素时候,则小数组就有序了。这样我们就得到了递归的条件即 low<high.
直接上图:
其实我当时也是,老师上课讲的思想也都懂,就是有始终不太明白他是怎么合并就有顺序了,这也是我递归遗忘的诟病。
我写的代码MERGE是合并并排序两个小数组的。(后面有代码)
其实了解了递归的步骤后很容易:继续上图:
↑
代码↓
#include <stdio.h>
#include <stdlib.h>
#define N 1000000
void Mergesort(int *A,int low,int high,int *temp)
{
if(low < high)
{
int mid = (high+low)/2;
Mergesort(A,low,mid,temp);
Mergesort(A,mid+1,high,temp);
MERGE(A,low,mid,high,temp);
}
}
void MERGE(int *A,int low,int mid,int high,int *temp)
{
int i=low;int j=mid;
int m=mid+1;int n=high;
int k=0;
//开始合并两个数组;
while(i <= j && m <= n)
{
if(A[i] <= A[m])
{
temp[k++] = A[i++];
}
else
{
temp[k++] = A[m++];
}
}
while(i <= j)
{
temp[k++] = A[i++];
}
while(m <= n)
{
temp[k++] = A[m++];
}
//把temp数组中的结果装回A数组
for(i = 0; i < k; i++)
{
A[i+low] = temp[i];
}
}
int main(int argc, const char * argv[])
{
int i,j;
int num[100000];
int temp[100000];
FILE* fp = fopen("1.txt","r");//读文件
FILE* stream = fopen("2.txt","w");//向文件中写入
if(fp==NULL)
{
printf("没找到文件");
return 0;
}
for(i=0;i<100000;i++)
{
fscanf(fp,"%d",&num[i]);
}
fclose(fp);
Mergesort(num,0,99999,temp);
for(j=0;j<100000;j++)
{
fprintf(stream,"%d\n",num[j]);
}
fclose(stream);
return 0;
}
我的代码中有txt文件的读写操作,因为作业需要,(✿◡‿◡)。