当前位置: 首页 > news >正文

单页式网站 seo保定广告设计公司

单页式网站 seo,保定广告设计公司,怎么做卡盟网站免费,厦门SEO_厦门网站建设1.归并排序 基本思想: 归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个…

1.归并排序

基本思想:
归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。 归并排序核心步骤:

相当于每次把待排数据分为两个子区间,如果每个子区间有序,再让两个子区间归并起来也有序,那整体就有序了。我们可以按照二叉树的思想,把子区间再分为两份,使子区间的子区间有序.......直到子区间分无可分为止。

具体过程如下:

那该如何让两个有序子区间归并呢?

直接在数组中肯定不行,这样会发生数据的覆盖。所以我们可以像之前合并两个有序数组一样,另外开辟一个空间tmp,依次比较两个有序子区间的值,每次比较后把较小的放在tmp中,如果其中一个子区间提前结束,就把另外一个子区间的剩余的数据全放进tmp,最后把tmp中的数据拷贝回原数组。

使用递归实现:

#include<stdio.h>
#include<stdlib.h>
void _MegeSort(int* a, int begin, int end,int*tmp)
{//只剩一个数据,递归结束if (begin == end){return;}int mid = (begin + end) / 2;//递归子区间,分为两部分_MegeSort(a, begin, mid, tmp);_MegeSort(a, mid+1, end, tmp);int begin1 = begin, end1 = mid;int begin2 = mid + 1, end2 = end;int j = begin;//两部分比较,每次小的放入tmpwhile (begin1 <= end1 && begin2 <= end2){if (a[begin1] < a[begin2]){tmp[j++] = a[begin1++];}else{tmp[j++] = a[begin2++];}}//哪部分有剩余,全部放入tmpwhile (begin1 <= end1){tmp[j++] = a[begin1++];}while (begin2 <= end2){tmp[j++] = a[begin2++];}//拷贝到原数组memcpy(a + begin, tmp + begin, sizeof(int) * (end - begin + 1));
}
void MegeSort(int* a, int n)
{int* tmp = (int*)malloc(sizeof(int) * n);_MegeSort(a, 0, n - 1, tmp);free(tmp);
}void Print(int* a, int n)
{for (int i = 0; i < n; i++){printf("%d ",a[i]);}printf("\n");
}
int main()
{int a[] = { 1,4,9,6,3,5,2,8,10,7,11,1};MegeSort(a, sizeof(a) / sizeof(int));Print(a, sizeof(a) / sizeof(int));return 0;
}

注意:

1. 因为每次递归的子区间都不一定是从0开始的,所以我们拷贝数据时,最好从begin的位置开始:

//拷贝到原数组
memcpy(a + begin, tmp + begin, sizeof(int) * (end - begin + 1));

2. 在代码中j作为tmp的坐标,每次往tmp中放入数据后都要加一,但不能初始化为0,否则每次递归进入,j的值都会清0,所以最好初始化:j=begin

归并排序的复杂度:

时间复杂度O(N*logN)

归并排序每次递归都要把待排数据分为两份,相当于二分法,那一共有logN层递归,而每次递归都要比较数据,要把每个数据都遍历一遍,每层的时间复杂度就是O(N),所以总共的时间复杂度是O(N*logN)。

空间复杂度:O(N) 

刚开始就开辟了空间,此时就已经是O(N)了,而递归过程中函数栈帧的创建是logN,所以总的空间复杂度是:O(N+logN),但是量级没变,还是O(N)。

2.非递归实现归并排序

非递归实现归并排序,我们只需模拟上述的递归过程即可,把递归过程转换为:把数据先分为2个一组,全部归并一遍,拷贝回原数组,然后4个一组,全部归并一遍,拷贝回原数组,再8个一组, 全部归并一遍,拷贝回原数组,

那我们就可以设置一个gap,两个数据为一组时,gap=1,每归并一组数据就往后跳2*gap步,直到全部归并一遍,再次分组,这次gap=2,每归并一组数据往后跳2*gap步,直到全部归并一遍,下次gap=4,跳2*gap步.....,直到gap>n就停止,

代码如下:

void MegeSortNonR(int* a, int n)
{int* tmp = (int*)malloc(sizeof(int) * n);if (tmp == NULL){perror("malloc fail\n");return;}int gap = 1;while (gap < n){int j = 0;for (int i = 0; i < n; i += 2 * gap){int begin1 = i, end1 = i + gap - 1;int begin2 = i + gap, end2 = i + 2 * gap - 1;//两部分比较,每次小的放入tmpwhile (begin1 <= end1 && begin2 <= end2){if (a[begin1] < a[begin2]){tmp[j++] = a[begin1++];}else{tmp[j++] = a[begin2++];}}//哪部分有剩余,全部放入tmpwhile (begin1 <= end1){tmp[j++] = a[begin1++];}while (begin2 <= end2){tmp[j++] = a[begin2++];}}memcpy(a, tmp, sizeof(int) * n);gap *= 2;}free(tmp);
}

测试一下:

上面结果看起来,我们排序成功了,但是上述代码真的对吗?

上面代码我们在测试时用的是8个数据,但是如果用9个、10个等,就会发现排序并不会成功,可能程序还会崩掉,这是为什么呢?

因为我们在分组时,是按照固定的2的次方分的,一旦数据个数不是2、4、8的次方,后面归并时就会发生越界问题。

下面我们给10个数据打印一下边界,会发现,有三种越界的方式,:

那我们对这三种情况分别做一下处理:

第1、2种情况出现时,我们直接break,第三种情况,我们修改边界,令end2=n-1,但是注意直接break后,第1、2种情况往tmp中归并时会少一部分数据(如上图蓝框所示),所以最后把tmp的数据往a中拷贝时,不能一次性全部拷贝回去,否则a中这些数据就永远丢失了,所以最好归并一段,拷贝一段,这样拷贝过去的数据只会把前面的数据覆盖,没参与归并的数据还在a中。

代码如下:

void MegeSortNonR(int* a, int n)
{int* tmp = (int*)malloc(sizeof(int) * n);if (tmp == NULL){perror("malloc fail\n");return;}int gap = 1;while (gap < n){int j = 0;for (int i = 0; i < n; i += 2 * gap){int begin1 = i, end1 = i + gap - 1;int begin2 = i + gap, end2 = i + 2 * gap - 1;if (end1 >= n || begin2 >= n){break;}//修正if (end2 >= n){end2 = n - 1;}//两部分比较,每次小的放入tmpwhile (begin1 <= end1 && begin2 <= end2){if (a[begin1] < a[begin2]){tmp[j++] = a[begin1++];}else{tmp[j++] = a[begin2++];}}//哪部分有剩余,全部放入tmpwhile (begin1 <= end1){tmp[j++] = a[begin1++];}while (begin2 <= end2){tmp[j++] = a[begin2++];}//归并一段,拷贝一段memcpy(a+i, tmp+i, sizeof(int) * (end2-i+1));}gap *= 2;}free(tmp);
}

3.计数排序

基本思想:

1. 统计每个数据出现的次数。

2. 根据数据的次数排序。 

如果我们要排序的数在0~9之间,我们可以像上面一样开辟10个int大小的空间,统计待排数据中每个数据的个数,在开辟出的数组的相应下标处计数,那如果我们要排序的数据在100~109之间呢?难道开辟110个空间吗?

当然不是,我们可以做相对映射,在开辟空间之前,先找到待排数据中的最小值和最大值,开辟空间的大小就是:sizeof(int)*(max-min+1),开辟出的数组下标应该是:0~9,0~9下标的位置分别对应的是100~109,计数时,在下标为该数据减待排数据中的最小值的位置统计次数,例如:109就在109-100=9的下标处统计次数,统计完排序的时候再加上最小值即可。

代码如下:

#include<stdio.h>
#include<stdlib.h>
void CountSort(int* a, int n)
{int min = a[0], max = a[0];//找最大值和最小值for (int i = 0; i < n; i++){if (a[i] < a[0]){min = a[i];}if (a[i] > a[0]){max = a[i];}}int range = max - min + 1;int* count = (int*)malloc(sizeof(int) * range);memset(count, 0, sizeof(int) * range);//计数for (int i = 0; i < n; i++){count[a[i] - min]++;}//排序int k = 0;for (int j = 0; j < range; j++){while (count[j]--){a[k++] = j + min;}}
}
//打印函数
Print(int* a, int n)
{for (int i = 0; i < n; i++){printf("%d ", a[i]);}printf("\n");
}
int main()
{int a[] = { 6,1,6,7,9,6,4,5,6,1 };CountSort(a, sizeof(a) / sizeof(int));Print(a, sizeof(a) / sizeof(int));return 0;
}

计数排序的复杂度:

时间复杂度:O(N+range)

寻找最大值和最小值时,遍历一遍数组,时间复杂度是:O(N),由于待排数据的范围是range,排序时所耗费的时间复杂度是:O(range),所以最终的时间复杂度是:O(N+range)

如果知道N和range的大小,N大,就是O(N),range大,就是O(range)

空间复杂度:O(range)

额外开辟的空间个数是range,所以空间复杂度就是:O(range)

4.排序的复杂度和稳定性

总结如下:

 以上就是排序学习的全部内容了,到这,数据结构的学习就告一段落了,近期会停更一段时间,用来复习,后面将继续学习C++的知识,

未完待续。。。

http://www.yayakq.cn/news/687198/

相关文章:

  • 九江浔阳网站建设企业网站及信息化建设
  • 移动端开发流程北京seo顾问
  • 成都餐饮网站建设视频广告对接平台
  • 唐山做网站的外贸出口工艺品怎么做外贸网站
  • 如何管理网站后台哪些网站上推广比较好
  • 修改网站模板自助网站建设 网易
  • 做网站应怎么缴税网站建设的发展历史与新方向
  • 网站不想被收录魔方优化大师官网
  • 建站方案策划书移动端购物网站建设
  • 营销型网站建设哪好wordpress 主题 制作
  • 深圳企业网站建设哪家专业2016网站设计规范
  • 从化市网站建设h5制作平台是什么意思
  • 企业网站推广的方法有哪几种上海史特做网站多少钱
  • 建电子商务网站多少钱企业运营管理岗位职责
  • 2021免费正能量网站暴雪时分电视剧免费观看
  • 地方网站需要什么手续长沙商城网站制作
  • 上海做网站站优云一一十七怎样讲卖灯的网站做的好
  • 江苏海通建设有限公司网站电商系统的哪家好
  • 西部数码手机网站龙岗做网站建设
  • 深圳图派做的网站后台加什么ios应用商店下载
  • 厦门网站建设案例网站的风格
  • 网站上不去的原因山东百度推广总代理
  • 商丘网站制作电话淘客招商网站选品库建设
  • 网站建设属什么资产深圳企业网络推广公司
  • 放网站的图片做多大分辨率石家庄网站建设公司怎么样
  • 前程无忧网深圳网站建设类岗位广州建站网站前十名
  • 随机图片网站网站建设之网页制作语言基础
  • 自创网站西安百度推广优化
  • 记事本做网站插图片wordpress 音乐页面
  • 网站购买利用c 做网站