本节开始讲解一下几个简单的算法,原理都在那本书上,大家自己看吧,我就不做搬运工了,这里不同的是,我把vector接口函数单独拿出来进行测试了,深深的体会到算法的奥妙之处,等你深入理解了你会情不自禁拍案叫绝的,废话不多说,因为这都是前段时间自己的练习代码,有详细的注释,不理解的请好好思考和看书,这里就不细说了


#include<iostream>
#include"F.h"using namespace std;//int disorde(int *A, int lo, int hi)
//{
//  int cnt = 0;
//
//  while (++lo < hi)
//  {
//      if (A[lo]-1 > A[lo])
//          cnt += 1;
//      cout << "lo = " << lo << endl;
//  }
//  //cout << "lo = " << lo << endl;
//  return (cnt == 0) ? -1 : 1;
//}//检查是否已经排好序
int disordered(int *A, int n)
{int cnt = 0;for (int i = 1; i < n; i++)if (A[i - 1] > A[i])cnt += 1;return cnt;
}//删除操作
void remove(int *A,int lo,int hi ,int n)
{//int i = 0;while (hi < n){A[lo++] = A[hi++];}
}//有序唯一化,清除重复数据
void uniquify(int *A, int n)
{//int i = 1;////while (i < n)//{// if (A[i - 1] != A[i])//        i++;//    remove(A, i,i+1, n);// //}int i = 0, j = 0;while (j++ < n)if (A[i] != A[j])A[i++] = A[j];//n = ++i;}//1.有序化的二分查找,该算法看上去复杂度均衡,其实不均衡,因此需要改进,使用
//菲波那切数列可以很好的改进复杂度的均衡。
int search(int *A,  const int &e, int lo, int hi)
{//复杂度为log(n)while (lo < hi){int mid = (lo + hi) >> 1;if (e < A[mid]) hi = mid;else if (A[mid] < e) lo = mid+1;else return mid;}return -1;
}
//2.有序的二分查找之斐波那契数列查找,可以均衡的改进复杂度
int searchfib(int *A, int const&e, int lo, int hi)
{Fib fib(hi - lo);while (lo < hi){while (hi - lo < fib.get()) fib.preve();int mid = lo + fib.get() - 1;if (e < A[mid]) hi = mid;else if (A[mid] < e) lo = mid + 1;else return mid;}return -1;
}//有序查找之继续优化
//改进均衡的方法还可以通过其他方法改进,即使的他们直接看上去很均衡
//该算法虽然可以均衡复杂度,但是无法及时推出,就是说即使mid命中了,也还要等到
//最后才能停止和返回,该版本整体性能稳定,但是不好的地方是如果查不到,只返回一个-1
//如果查不到这插入,那么这个算法就不是很好,无法得到合适的插入位置,因此需要进一步要求
//因此在此基础上可以继续改进
int searchPro(int *A, const int &e, int lo, int hi)
{while (1 < hi - lo){int mid = (lo + hi) >> 1;(e < A[mid]) ? hi = mid : lo = mid;}return (e == A[lo]) ? lo : -1;
}
//有序查找的终极优化,该算法在循环结束之后,无论成功
//与否,只需返回lo - 1即可
int searchPro_(int *A, const int &e, int lo, int hi)
{while (lo < hi){int mid = (lo + hi) >> 1;(e < A[mid]) ? hi = mid : lo = mid + 1;}return --lo;//在寻找到最后时,hi和lo重合了,也就是说他们指向一个地方//如果,存在这个元素,则返回对应的下标,如果不存在这个元素则返回最近这个数的下标,//以此可以使用插入算法,进行插入即可
}
int Search(int *A, const int &e, int n)
{//return search(A, e, 0, n); //return searchfib(A, e, 0, n);//return searchPro(A, e, 0, n);return searchPro_(A, e, 0, n);
}//通过上面我们发现如果排好序了,就可以更高效的进行处理元素了
//因此排序的重要性就不言而喻了,下面我们就开始排序算法实践void swap(int &a, int &b)
{a = a + b;b = a - b;a = a - b;
}//1.冒泡排序(最基本的冒泡排序),这个复杂度很高,达到O(n^2),即使已经排序完成
//还是不能及时停止推出,在此基础上需要改进算法,使其能够及时退出
void bubblesort(int *A, int n)
{while (0 < n){for (int i = 1; i < n; i++){if (A[i - 1] > A[i]) swap(A[i - 1], A[i]);}n--;}}
//2.为了达到及时退出的目的,我们需要考虑每趟的遍历是否发生交换,
//如果发生交换,则继续排序,如果一趟比较后没发生交换,说明已经排好序了,此时可以
//终止程序,由此我们需要检测每趟是否排序,怎么实现呢?可以如下:
void bubblesort_pro(int *A, int n)
{//int flag = 0;//这里是为了输出遍历了几趟,来计数使用的bool sorted = false;//刚进函数,还没排序,假设没排好序while (!sorted){      sorted = true;//假设已经排好序了,n每次更新说明,已经走完一趟了,这里设置//为true,是假设走了一趟都没有发生交换,说明已经排好序,符合逻辑,如果发生交换我们//置为falsefor (int i = 1; i < n; i++)if (A[i - 1] > A[i]){swap(A[i - 1], A[i]);sorted = false; //进来这里说明还是存在调换的,因此不能保证已排好序,需要把sorted改为false}n--;//flag++;}//cout << "遍历了:" << flag << endl;
}//上面该进的冒泡排序算法,已经达到了我们的要求了,但是对于最糟糕的情况,复杂度还是O(n^2)
//一边情况可以到达O(n),这是在存在排好序的情况下,而且他是根据是否有逆序来判断,虽然有时候
//可以达到一定的效果,但是还有缺点,例如如果有一段序列,排好序的是已经分好几段了,那么根据上面
//这个算法将没有那么高效了,我们知道,若最后一部分已经排好序了,算法还是会进行比对的,
//如果现在我们希望算法能做到这样,就是排好序的我们不比对,只针对乱序的进行排序
//这样就可以很高效的进行排序了,那么这个思想如何实现呢?
//思想原理是可以通过记录最后一次发生交换的地方,这样下一次就可以直接改变待排序的长度
//也就是说,从后向前不断缩减待排序的内容,如下
int bubblesort_pro_pro(int *A, int n)
{int last = 0;//假设逆序对最先从最左端开始的int i = 0;while (++i <n){      if (A[i-1] > A[i]){swap(A[i - 1], A[i]);             last = i;}         cout << "last = " << last << " " << endl;}return last;
}
void bubble_P(int *A, int n)
{while (0 < (n = bubblesort_pro_pro(A, n)));
}
//上面的算法可以很好的解决了前面提的要求,同时复杂度达到了O(n)的数量级,以上就是冒泡排序的各版本了,至于其他的版本,这些都差不多
//只是用处不引用,思想是一样的,大家需要深入理解其精髓。//下面引入归并排序算法,归并排序和冒泡排序的不同之处在,有序序列的情况如何,
//其复杂的都是nlogn的复杂度;
void merge(int *ele, int lo, int mid, int hi)
{int *A = ele + lo;int lb = mid - lo;int *B = new int[lb];for (int i = 0; i < lb; B[i] = A[i++]);int lc = hi - mid;int *C = ele + mid;for (int i = 0, j = 0, k = 0; j < lb || k < lc;){if (j < lb && (lc <= k || B[j] <= C[k])) A[i++] = B[j++];if (k < lc && (lb <= j || C[k] < B[j])) A[i++] = C[k++];}delete[] B;
}//精简版版归并排序算法,精简其实就体现在两个if条件语句中
void merge_sim(int *arr, int lo, int mid, int hi)
{//if (hi - lo < 2) return;int *A = arr + lo;int lb = mid - lo;int *B = new int[lb];for (int i = 0; i < lb; B[i] = A[i++]);int *C = arr + mid;int lc = hi - mid;for (int i = 0, j = 0, k = 0; (j < lb) ;)// || (k < lc);){//if (j < lb && (k >= lc || B[j] < C[k])) A[i++] = B[j++];if (k < lc && C[k] < B[j]) A[i++] = C[k++];//if (k < lc && (j >= lb || C[k] < B[j])) A[i++] = C[k++];if (lc <= k || B[j] <= C[k]) A[i++] = B[j++];}delete[] B;}void mergesort(int*A, int lo,int hi)
{if (hi - lo < 2) return;int mid = (lo + hi) >> 1;mergesort(A, lo, mid);mergesort(A, mid, hi);merge_sim(A, lo, mid, hi);}int main()
{//int arr[] = { 2,1,3,0,5,4,8,7,6,9 };//int arr[10] = {3,4,5,6,7,8,9,10,11,12 };int arr[10] = { 3,5,4,6,8,7,9,11,10,12 };for (int i = 0; i < (int) size(arr); i++)cout << arr[i] << " ";cout << endl;//cout << disordered(arr, 10) << endl;//uniquify(arr,10);//for (int i = 0; i < size(arr); i++)//   cout << arr[i] << " ";//cout << Search(arr,100, 10) << endl;//Fib fib(0);//for (int i = 0; i < 40; i++)//   cout << fib.next() << " ";//cout << endl;//排序//bubblesort(arr, size(arr));//bubble_P(arr, 10);mergesort(arr, 0, 10);for (int i = 0; i <(int) size(arr); i++)cout << arr[i] << " ";cout << endl;//int(size) = int(size*);return 0;
}

有序序列的二分查找、冒泡排序、归并排序算法实战解析相关推荐

  1. 【二分查找延伸--实际算法应用】数组类题目

    声明:博主是基于labuladong微信公众号文章模板驱动刷题,进行的自我刷题感悟和记录在此. 模板详情见labuladong微信公众号文章文末:原创于自己在此基础上的笔记.感悟.整合其它文献和自己的 ...

  2. BinarySearch 有序表的二分查找

    BinarySearch 有序表的二分查找 思路: 前提是线性表采用顺序存储(通常从小到大),然后在有序表中取中间记录作为比较对象,若给定值与中间记录的关键字相等,则查找成功:若小于,则在中间记录的左 ...

  3. 【C语言函数3.2】写一个函数,实现一个整形有序数组的二分查找代码

    写一个函数,实现一个整形有序数组的二分查找代码 #include <stdio.h>int binary_search(int a[], int k, int s) {int left = ...

  4. 对长度为200的有序表进行二分查找_程序员常用的查找算法(顺序、二分、插值、分块、斐波那契)...

    顺序查找 基本思想 属于线性查找和无序查找,从一端开始顺序扫描,直到找到与目标值value相等的元素. 这是最基本的查找方法,也是时间复杂度最高的查找算法. 在数据过多时,这种方法并不适用. 代码实现 ...

  5. 有序数组二分查找java_详解Java数据结构和算法(有序数组和二分查找)

    一.概述 有序数组中常常用到二分查找,能提高查找的速度.今天,我们用顺序查找和二分查找实现数组的增删改查. 二.有序数组的优缺点 优点:查找速度比无序数组快多了 缺点:插入时要按排序方式把后面的数据进 ...

  6. 二分查找、分治算法——汉诺塔问题

    一.二分查找算法(非递归) 1)二分查找法只适用于从有序的数列中进行查找(比如数字和字母等),将数列排序后在进行查找 2)二分查找算法的运行时间为对数时间,即查找到需要的目标位置最多只需要log以2为 ...

  7. java二分查找法_java算法之二分查找法的实例详解

    java算法之二分查找法的实例详解 原理 假定查找范围为一个有序数组(如升序排列),要从中查找某一元素,如果该元素在此数组中,则返回其索引,否则返回-1.通过数组长度可取出中间位置元素的索引,将其值与 ...

  8. 1.1.10 从二分查找BinarySearch开启算法学习之路---《java算法第四版》

    文章目录 0.前言 1.功能 2.示例 有两个名单tinyW.txt和tinyT.txt,将tinyT.txt名单中不在tinyW.txt的数据打印出来 ① 实现原理 ② 实现代码 ③ 性能分析 0. ...

  9. python 二分查找_LeetCode基础算法题第120篇:二分查找算法

    技术提高是一个循序渐进的过程,所以我讲的leetcode算法题从最简单的level开始写的,然后> 到中级难度,最后到hard难度全部完.目前我选择C语言,Python和Java作为实现语言,因 ...

最新文章

  1. Hadoop的基础架构
  2. 程序员网购18年不拆快递!意外离世后满屋快递被拆开,价值3500万!
  3. Could not install packages due to an Environment Error: [Errno 13] Permission denied 解决方案
  4. Mybatis用#{}从传递过来的参数中取值
  5. Spring Batch教程–最终指南
  6. 外连接就是允许不满足条件的字段查询出来
  7. B端产品经理要掌握的基本功
  8. 改文案、删微博又道歉 广汽蔚来自导自演“比特币购车”乌龙案
  9. java季度第一天_Java得到年在一个季度的错误的第一天
  10. visionpro 图片格式转海康图片格式
  11. JPA+Hibernate 3.3 ——第一个JPA程序
  12. 用FileZilla搭建的Ftp其他电脑无法访问的问题
  13. 基于jQuery带标题的图片3D切换焦点图
  14. 联想ghost重装系统_【一键ghost装系统教程】一键ghost重装系统_一键ghost安装教程...
  15. 无法打开包括文件: “ui_XXX.h”: No such file or directory
  16. 2387: [Ceoi2011]Traffic
  17. 使用单链表统计英文文本单词个数
  18. vscode 如何快速跳出括号
  19. 论文阅读:Regularizing Deep Networks with Semantic Data Augmentation
  20. 第十七届全国大学生智能汽车竞赛创意组-百度智慧交通(丝绸之路)

热门文章

  1. Linxu 常用命令大全(一)
  2. Python学习笔记(六)—几个标准类型内建函数
  3. 哪些情况需用到数据分析工具
  4. 图像处理、分析与机器视觉(基于labview)_基于3D技术的机器视觉解决方案
  5. python如何屏幕截图_Python编写屏幕截图程序方法
  6. AcWing 788. 逆序对的数量
  7. POJ2104 K-th Number (平方分割 + 二分)
  8. 以下选项中表述为oracle,oracle 选择题
  9. a4如何打印双面小册子_怎样将十几几十页的长文件文档打印成A4纸对折的小册子?...
  10. Shell脚本编程之(一)Shell脚本简介