菜鸟笔记- 算法 7月18日学习(归并排序)

归并排序

网上思路:

基本思想:归并(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);
		}

	}

猜你喜欢

转载自blog.csdn.net/qq_25744257/article/details/81104666