归并排序
网上思路:
基本思想:归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。
思路:
每个元素看作一个有序列表,再两两合并 最后全部合并
怎么写 想一哈
先是 合并前后两个数 最后一个不合并
再合并前后两个数组 ,但是我怎么知道哪些是已经合并的有序数组
2017 7/11 整体思路
先排序一个数组内的数字,
1 首先排序一个数组内的数字,做到前后有序,
2 怎么分出数组来排序
3 确定每次合并哪些数组,怎么两两合并
重新整理思路
观察排序长度2,4,8 这样增长
选取一个变量dk,每次让dk*2
确定一个排序长度2,每次自增
确定两个循环 ,第一个循环,每次增长数组长度,
第二个循环,在这个数组里面比较。
每个归并排序用插入排序 笨方法
代码:
#include "stdafx.h"
#include <windows.h>
void swap(int arr[], int o, int n)
{
int temp = arr[o];
arr[o] = arr[n];
arr[n] = temp;
}
void print(int arr[], int length) {
for (int j = 0; j<8; j++) {
printf("%d", arr[j]);
}
printf("\n");
}
//每组排序里面用插入排序
void insertSort(int arr[], int start, int end)
{
for (int i = end; i > start; i--)
{
for (int j = end - 1; j >= start; j--)
{
if (arr[j] > arr[j + 1])
{
swap(arr, j, j + 1);
}
}
}
}
//最开始是开始,后面也开始
void mergeGroup(int arr[],int start,int end,int dk)
{
if (dk >=end)
{
dk = end;
}
printf("dk=%d", dk);
for (int i = start; i < end; i = i + dk)
{
if (i + dk - 1>=end)
{
break;
}
//每个组里面进行插入排序
//for (int j = i + dk-1; j > i; j--)
//{
// printf("j=%d", j);
// printf(" j-1=%d", j-1);
//
// if (arr[j] < arr[j - 1])
// {
// swap(arr, j, j - 1);
//
// }
//}
insertSort(arr, i, i + dk - 1);
}
}
void sort(int arr[], int length)
{
//分组条件
int dk = 2;
while (dk <= length)
{
mergeGroup(arr, 0, length, dk);
dk = dk * 2;
printf("dk=%d", dk);
print(arr, 8);
}
}
int main()
{
int arr[8] = { 3,1,5,7,2,4,9,6 };
print(arr, 8);
sort(arr, 8);
print(arr, 8);
system("pause");
return 0;
}
重新理思路:
归并排序不对
核心是归并两个序列,而我在归并时使用的插入排序。
基本思想,用辅助数组,在两个数组合并时候,把小数依次插入这个辅助数组,使这个新数组变成最后合并的数组,
比较是两个数组从开始下标到结束下标依次比较
错误记录:
1 在合并时,初时下标不用赋值,下标是传进来的下标,i是已知的,应该用j承接其它变量
源代码:for (int i = m + 1, j = i, k = i; i<=n&&j<=m; ++k)
改代码:for ( j = m + 1, k = i; i <= m&&j <= n; ++k)
2 只从中选择了可能只有一半元素大,比如前面集合每个都小于后面集合的数,当i=m,退出循环,此时,合并的集合还有一半元素尚未合并,所以要去找剩下的。因为前面集合比如
集合1 {1,3,5} 2 {2,9,10}
1,2,3,5 此时 i>m 退出循环
还剩下 集合2 的 9 10 未排序 因为肯定比前面的大,又是有序增大的,所以依次加入进来,
或者 集合1 {2,9,10} 2 {1,3,5}
1,2,3,5 此时 j>n退出循环
剩下集合 1 的9 ,10 未排 ,因为肯定比前面的大,又是有序增大的,所以依次加入进来,
源代码: 无
改代码:while (i <= m) rf[k++] = r[i++];
while (j <= n) rf[k++] = r[j++];
2018 7 16
合并新表用数组承接,把两个数组的数字由小到大依次存放这个临时变量数组
比较两个合并的数组,小的放进临时变量,大的不管,最后再依次全部放入。
错误记录:
最开始定义的两个长度其实就定义了两个合并数组的长度。
2018 7 17
初始理解:
先合并两个数组
把两个集合里面的数字由小到大依次放入变量数组
轮询数字,由第一个集合结尾下标 和第二个集合结尾下标组成。
我的错误
并没有寻找两个集合的开始 结尾下标,所以代码错误
源代码: int s = 2;
len = s * len;
改代码: int s = len;
len = s * 2;
遇到难题 需要循环两次,又需要循环后的数字来判断数值大小
最开始要把单个数字当成集合,而不是最开始就用2个当集合排序,都没排序怎么确定有序,
源代码: mergeTwo(fArr, tArr, i, i + s, i + len + 1);
改代码: Merge(q, rf, i, i+ s-1, i+ len-1 );
运行两次,所以代码修改为大于等于,当两个数组的开始下标等于结束下标时候结束
源代码: while (start <mid&&secondS<end)
改代码: while (start <=mid&&secondS<=end)
交换数组,不能直接用指针符号,无效
源代码: tmp = q; q = rf; rf = tmp;
改代码:
void swapArr(int arr[], int temp[],int length) {
for (int j = 0; j<length; j++) {
arr[j] = temp[j];
}
}
可能集合不能刚好被2除尽 ,两个集合不等长
源代码: while (i < length) {} if(len < length){}
改代码:while (i+len < length){} if (i+s < length){}
最后代码的合并 不会合并,写错,应该还是以I为标准
源代码: mergeTwo(fArr, tArr, 0, len, length-1);
改代码: mergeTwo(fArr, tArr, 0, i + s-1, length-1);
//2018 7 18
错误
交换数组不等长时候替换数组长度是之前排序长度
源代码: swapArr(fArr, tArr, i);
改代码:swapArr(fArr, tArr, length);
所有代码:
#include "stdafx.h"
#include <windows.h>
void swap(int arr[], int o, int n)
{
int temp = arr[o];
arr[o] = arr[n];
arr[n] = temp;
}
void print(int arr[], int length) {
for (int j = 0; j<length; j++) {
printf("%d", arr[j]);
}
printf("\n");
}
void swapArr(int arr[], int temp[], int length) {
for (int j = 0; j<length; j++) {
arr[j] = temp[j];
}
}
void mergeTwo(int *fArr, int *tArr, int start, int mid, int end)
{
int i = start;
int secondS = mid + 1;
while (start <= mid&&secondS <= end)
{
if (fArr[start] < fArr[secondS])
{
tArr[i] = fArr[start];
start++;
}
else
{
tArr[i] = fArr[secondS];
secondS++;
}
i++;
}
while (start <= mid)
{
tArr[i] = fArr[start];
i++;
start++;
}
while (secondS <= end)
{
tArr[i] = fArr[secondS];
i++;
secondS++;
}
}
void mergeSort(int *fArr, int *tArr, int length)
{
int len = 1;
while (len < length)
{
int s = len;
len = s * 2;
int i = 0;
//排序两个长度相同的集合
while (i + len < length)
{
mergeTwo(fArr, tArr, i, i + s - 1, i + len - 1);
i = i + len;
}
swapArr(fArr, tArr, i);
//不等长暂未研究透
//这里的错误是永远少一个数
if (i< length)
{
mergeTwo(fArr, tArr, 0, i-1, length - 1);
swapArr(fArr, tArr, length);
}
}
}
void sort(int arr[], int length)
{
int tmpArr[9];
mergeSort(arr, tmpArr, length);
print(arr, 9);
}
int main()
{
int arr[9] = { 3,1,5,7,2,4,9,6,8 };
print(arr, 9);
sort(arr, 9);
print(arr, 9);
system("pause");
return 0;
}
void mergeSort2(int *fArr, int *tArr, int length)
{
int len = 1;
while (len < length)
{
int s = len;
len = s * 2;
int i = 0;
//排序两个长度相同的集合
while (i + len < length)
{
mergeTwo(fArr, tArr, i, i + s - 1, i + len - 1);
i = i + len;
print(tArr, 9);
}
swapArr(fArr, tArr, i);
//不等长暂未研究透
if (i + s< length)
{
mergeTwo(fArr, tArr, 0, i + s - 1, length - 1);
swapArr(fArr, tArr, length);
}
}