C/C++ 数据结构之算法(面试)
数据结构中的排序算法。
排序算法的相关知识:
(1)排序的概念:所谓排序就是要整理文件中的记录,使之按关键字递增(或递减)次序排列起来。
(2)稳定的排序方法:在待排序的文件中,若存在多个关键字相同的记录,经过排序后这些具有相同关键字的记录之间的相对次序保持不变,该排序方法是稳定的。相反,如果发生改变,这种排序方法不稳定。
(3)排序算法的分类(分为5类):插入排序、选择排序、交换排序、归并排序和分配排序。
(4)排序算法两个基本操作:<1>比较关键字的大小。
<2>改变指向记录的指针或移动记录本身。
具体的排序方法:
插入排序
<1>插入排序(Insertion Sort)的思想:每次将一个待排序的记录按其关键字大小插入到前面已经排好序的子记录中的适当位置,直到全部记录插入完成为止。
<2>常用的插入排序方法有直接插入排序和希尔排序。
(1)直接插入排序
<1>算法思路:把一个记录集(如一个数组)分成两部分,前半部分是有序区,后半部分是无序区;有序区一开始有一个元素r[0],无序区一开始是从r[1]到之后的所有元素;然后每次从无序区按顺序取一个元素r[i],拿到有序区中由后往前进行比较,每次比较时,有序区中比r[i]大的元素就往后移动一位,直到找到小于r[i]的元素,这时r[i]插到小元素的后面,则完成一趟直接插入排序。如此反复,从无序区不断取元素插入到有序区,直到无序区为空,则插入算法结束。
<2>算法演示:
//直接插入排序:#include<iostream> using namespace std;
void InsertSort(int r[],int n);
int main() { int r[]={24,1,56,2,14,58,15,89}; InsertSort(r,8); for(int i=0;i<8;i++) { cout<<r[i]<<'\t'; } cout<<endl; return 0; }
void InsertSort(int r[],int n) { for(int i=1;i<n;i++) { for(int j=i-1,s=r[i];s<r[j] && j>=0;j--) { r[j+1]=r[j]; } r[j+1]=s; } }
(2)折半插入排序
<1>算法思路:我们看到在直接插入排序算法中,需要在有序区查找比r[i]的小的元素,然后插入到这个元素后面,但这里要注意这个元素是从无序区算第一个比r[i]小的元素。折半插入排序就是在有序区折半查找这个元素。
<2>算法演示:
//折半插入排序#include<iostream> using namespace std;
void BinInsertSort(int r[],int n);
int main() { int r[]={53,34,76,23,55,28,63,88,34,66}; BinInsertSort(r,10); for(int i=0;i<10;i++) { cout<<r[i]<<"\t"; } cout<<endl; return 0; }
void BinInsertSort(int r[],int n) { for(int i=1;i<n;i++) { int s=r[i]; int low=0; int high=i-1; while(low <= high) { int mid=(low+high)/2; if(s < r[mid]) { high=mid-1; } else { low=mid+1; } } for(int j=i-1;j>=high+1;j--) { r[j+1]=r[j]; } r[high+1]=s; //r[high+1]是要找的元素 } }
(3)希尔排序(Shell Sort)
<1>算法思路:把整个记录近一个步长step(一般取记录长度的1/2),分成step个组,再分别对每个级进行直接插入排序;然后再把整个记录近一个新的步长(一般取step/2)分成step/2个组,再分别对每个组进行直接插入排序;如此不断的缩小步长,反复分组排序,直到步长等于1为此(步长为1则不可能再分组,1是元素之间距离的最小值)。可以看出,希尔排序实质是一种分组插入方法。
<2>算法演示:
//希尔排序:#include<iostream> using namespace std;
void ShellSort(int r[],int n); int main() { int r[]={24,1,56,2,14,58,15,89}; ShellSort(r,8); for(int i=0;i<8;i++) { cout<<r[i]<<'\t'; } cout<<endl; return 0; }
void ShellSort(int r[],int n) { int step=n/2; while(step >= 1) { for(int i=step;i<n;i+=step) { for(int j=i-step,s=r[i];s<r[j] && j>=0;j-=step) { r[j+step]=r[j]; } r[j+step]=s; } step/=2; } }
选择排序
<1>选择排序的思想:每一趟从待排序的记录中选出关键字最小的记录,顺序放在已经排好的记录最后,直到全部记录排序完毕。
<2>常用的选择排序方法有直接选择排序和堆排序。
(1)直接选择排序
<1>算法思路:把待排序的n个元素看成一个有序区和一个无序区,开始的时候有序区为空,无序区包含了全部n个元素。排序的时候,每次从无序区中选择比较出其中最小一个元素放到有序区中。如此反复操作,无序区中每小一个元素,有序区中就多一个元素,直到无序区的所有元素都转到有序区中。
<2>算法演示:
//简单选择排序:#include<iostream> using namespace std;
void SelectSort(int r[],int n);
int main() { int r[]={53,34,76,23,55,28,63,88,34,66}; SelectSort(r,10); for(int i=0;i<10;i++) { cout<<r[i]<<"\t"; } cout<<endl; return 0; }
void SelectSort(int r[],int n) { for(int i=0;i<n-1;i++) { int small_loc=i; for(int j=i+1;j<n;j++) { if(r[small_loc] > r[j]) { small_loc=j; } } if(small_loc != i) { int temp=r[i]; r[i]=r[small_loc]; r[small_loc]=temp; } } }
(2)堆排序
<1>算法思路:大根堆二叉树中的非终端结点的元素值均大于它的左右孩子的值,因此知道堆的最大值是它的根结点。当根结点移出,则重新调整堆后,堆的次大值称为根结点,依次操作,可以得到堆的从大到小的有序序列。这个算法过程就是堆排序。
堆排序有一个建堆、筛选堆、调整堆的过程。
<2>算法演示:
//堆排序:#include<iostream> using namespace std;
void HeapAdjust(int r[],int i,int j); void HeapSort(int r[],int n);
int main() { int r[]={53,34,76,23,55,28,63,88,34,66}; HeapSort(r,10); for(int i=0;i<10;i++) { cout<<r[i]<<"\t"; } cout<<endl; return 0; }
void HeapAdjust(int r[],int i,int j) //调整堆{ int child=2*i; int temp=r[i]; //temp临时存放根结点 while(child <= j) //沿大儿子向下调整 { if(child<j && r[child+1]>r[child]) child++; if(temp >= r[child]) break; r[child/2]=r[child]; child=2*child; } r[child/2]=temp; }
void HeapSort(int r[],int n) //建堆{ for(int i=(n-1)/2;i>=0;--i) { HeapAdjust(r,i,n-1); //初始建堆 } for(i=n-1;i>0;--i) { //将当前堆顶元素与当前堆尾元素互换 int temp=r[0]; r[0]=r[i]; r[i]=temp; HeapAdjust(r,0,i-1); //将剩下的元素重新调整成堆 } }
交换排序
<1>交换排序的思想:两两比较待排序记录的关键字,发现两个记录的次序相反时即进行交换,直到没有反序的记录为止。
<2>常用的交换排序方法有冒泡排序和快速排序。
(1)冒泡排序
<1>算法思路:通过相邻元素的值的大小比较,并交换值较大的(较小的)元素,使得元素从一端移到到另一端,就像水底冒出的气泡一样。
<2>算法演示:
//起泡法排序:#include<iostream> using namespace std; #define N 5 //N为数的总个数
void BubbleSort(int r[],int n);
int main() { int i; int a[N]; cout<<"请输入"<<N<<"个数字:"; for(i=0;i<N;i++) { cin>>a[i]; } BubbleSort(a,N); for(i=0;i<N;i++) { cout<<a[i]<<"\t"; } cout<<endl; return 0; }
void BubbleSort(int r[],int n) { for(int i=0;i<n-1;i++) //进行n-1次循环,实现n-1趟比较 { for(int j=0;j<n-1-i;j++) //在每一趟中进行n-1-i次比较 { if(r[j]>r[j+1]) { int temp=r[j]; r[j]=r[j+1]; r[j+1]=temp; } } } }
(2)快速排序
<1>算法思路:通过一趟排序将准备排序的元素集合分成两个部分,其中一部分的元素的值都小于另一部分,然后对这两部分的元素集合内部再分别重复进行上面的排序过程,直到所有的元素都排列有序。
<2>算法演示:
//快速排序:#include<iostream> using namespace std;
int Partition(int r[],int low,int high); void QuickSort(int r[],int low,int high);
int main() { int r[]={53,34,76,23,55,28,63,88,34,66}; QuickSort(r,0,10-1); for(int i=0;i<10;i++) { cout<<r[i]<<"\t"; } cout<<endl; return 0; }
int Partition(int r[],int low,int high) { int pivotkey=r[low]; int i=low; int j=high; while(i<j) { while(i<j && r[j]>pivotkey) j--; if(i<j){r[i]=r[j];i++;} while(i<j && r[i]<pivotkey) i++; if(i<j){r[j]=r[i];j--;} } r[j]=pivotkey; return j; }
void QuickSort(int r[],int low,int high) { if(low<high) { int pivot=Partition(r,low,high); QuickSort(r,low,pivot-1); QuickSort(r,pivot+1,high); } }
归并排序
<1>归并排序的思想:假设数组r有n个元素,那么可以看成数组r是由n个有序的子序列组成,每个子序列的长度为1,然后再两合并,得到了一个长度是2(或1)的有序子序列,再两两合并,如此重复,直到得到一个长度为n的有序数据序列为止,这种排序方法称为二路归并排序。
<2>常用的交换排序方法有二路归并排序和三路归并排序。
(1)二路归并排序
<1>算法思路:如上。
<2>算法演示:
//二路归并排序#include <iostream> using namespace std; int *a=new int[20]; int n=0;
//归并排序,排序结果放到了b[]中void Merge(int a[],int b[],int left ,int mid,int right)//此处的right指向数组中左后一个元素的位置{ int i=left; int j=mid+1; int k=left; while(i<=mid && j<=right) { if(a[i]<=a[j])b[k++]=a[i++]; else b[k++]=a[j++]; } while(i<=mid) b[k++]=a[i++]; while(j<=right) b[k++]=a[j++]; }
//从b[]中又搬到了a[]中void Copy(int a[],int b[],int left,int right)//right同上{ for(int i=left;i<=right;i++) a[i]=b[i]; }
//划分并排序void MergeSort(int a[],int left,int right)//同上{ int *b = new int[right-left+1]; if(left<right) { //将当前传经来的数组划分成更小的大小几乎相同的数组 int i=(left+right)/2; MergeSort(a,left,i); MergeSort(a,i+1,right); //将小数组合成大数组,同时排序,结果放到b[]中 Merge(a,b,left,i,right); //从b[]中挪到a[]中 Copy(a,b,left,right); } }
void Input() { cout<<"Please Input array's size:"; cin>>n; cout<<"Array's elemants:"<<endl; for(int i=0;i<n;i++) cin>>a[i]; //调用算法 MergeSort(a,0,n-1); }
void Output() { for(int i=0;i<n;i++) cout<<a[i]<<" "; cout<<endl; }
int main() { Input(); Output(); return 0; }
C/C++ 数据结构之算法(面试)的更多相关文章
- 面试常考的常用数据结构与算法(zz)
数据结构与算法,这个部分的内容其实是十分的庞大,要想都覆盖到不太容易.在校学习阶段我们可能需要对每种结构,每种算法都学习,但是找工作笔试或者面试的时候,要在很短的时间内考察一个人这方面的能力,把每种结 ...
- 大公司面试经典数据结构与算法题C#/Java解答
几个大公司(IBM.MicroSoft and so on)面试经典数据结构与算法题C#解答 1.链表反转 我想到了两种比较简单的方法 第一种是需要开一个新的链表,将原链表的元素从后到前的插入到新链表 ...
- 数据结构+算法面试100题~~~摘自CSDN
数据结构+算法面试100题~~~摘自CSDN,作者July 1.把二元查找树转变成排序的双向链表(树) 题目:输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表.要求不能创建任何新的结点,只调 ...
- C++程序员面试题目总结(涉及C++基础、多线程多进程、网络编程、数据结构与算法)
说明:C++程序员面试题目总结(涉及C++基础知识.多线程多进程.TCP/IP网络编程.Linux操作.数据结构与算法) 内容来自作者看过的帖子或者看过的文章,个人整理自互联网,如有侵权,请联系作者 ...
- 数据结构与算法-江西师范大学865(针对考研or面试)
可以加我微信chenyoudea免费要江西师范大学865资料全套pdf 目录 第一篇 数据结构与算法(针对考研or面试) 第二篇 真题演练 第三篇 复试 第四篇 推荐阅读 第一篇 数据结构与算法(针对 ...
- php面试之数据结构和算法
二.数据结构和算法 1.使对象可以像数组一样进行foreach循环,要求属性必须是私有.(Iterator模式的PHP5实现,写一类实现Iterator接口)(腾讯) <?php class T ...
- 数据结构与算法JavaScript (一) 栈
序 数据结构与算法JavaScript这本书算是讲解得比较浅显的,优点就是用javascript语言把常用的数据结构给描述了下,书中很多例子来源于常见的一些面试题目,算是与时俱进,业余看了下就顺便记录 ...
- 翻阅《数据结构与算法javascript描述》--数组篇
导读: 这篇文章比较长,介绍了数组常见的操作方法以及一些注意事项,最后还有几道经典的练习题(面试题). 数组的定义: JavaScript 中的数组是一种特殊的对象,用来表示偏移量的索引是该对象的属性 ...
- 数据结构与算法javascript描述
<数据结构与算法javascript描述>--数组篇 导读: 这篇文章比较长,介绍了数组常见的操作方法以及一些注意事项,最后还有几道经典的练习题(面试题). 数组的定义: JavaScri ...
- Python 数据结构和算法
阅读目录 什么是算法 算法效率衡量 算法分析 常见时间复杂度 Python内置类型性能分析 数据结构 顺序表 链表 栈 队列 双端队列 排序与搜索 冒泡排序 选择排序 插入排序 希尔排序 快速排序 归 ...
随机推荐
- Android MVP 构架封装
上一篇我们简单实现了一个MVP的构架,下面我们来做一个简单的封装使其使用更简单方便 源码地址RxMVP分支Tag03 最终实现目录结构如下 BasePresenter 如果每一个Activity都需要 ...
- 强大的json工具:fastJson
fastJson FastJSON是一个很好的java开源json工具类库,相比其他同类的json类库,它的速度的确是fast,最快!但是文档做得不好,在应用前不得不亲测一些功能. 实际上其他 ...
- WebService 之 实例学习一
新建一个空网站项目,添加新建项 “ Web 服务 ”. 一.WebServiceDemo.asmx 文件,默认内容如下: <%@ WebService Language="C#&quo ...
- PHP高级教程-Cookie
PHP Cookie cookie 常用于识别用户. Cookie 是什么? cookie 常用于识别用户.cookie 是一种服务器留在用户计算机上的小文件.每当同一台计算机通过浏览器请求页面时,这 ...
- Hibernate(八)多对多映射
一.创建数据表 --学生证表 create table paper ( pid number primary key, pdesc ) , sid number references student( ...
- 常见的前端UI框架
Bootstrap 首先说 Bootstrap,估计你也猜到会先说或者一定会有这个( 呵呵了 ),这是说明它的强大之处,拥有框架一壁江山的势气.自己刚入道的时候本着代码任何一个字母都得自己敲出来挡我者 ...
- 使用Elasticsearch 与 NEST 库 构建 .NET 企业级搜索
使用Elasticsearch 与 NEST 库 构建 .NET 企业级搜索 2015-03-26 dotNET跨平台 最近几年出现的云计算为组织和用户带来了福音.组织对客户的了解达到前所未有的透彻, ...
- 图文例解C++类的多重继承与虚拟继承
文章导读:C++允许为一个派生类指定多个基类,这样的继承结构被称做多重继承. 在过去的学习中,我们始终接触的单个类的继承,但是在现实生活中,一些新事物往往会拥有两个或者两个以上事物的属性,为了解决这个 ...
- Java实现可视化迷宫
代码地址如下:http://www.demodashi.com/demo/14547.html 需求 使用深度优先算法求解迷宫路径,使用Java实现求解过程的可视化,可单步运行,形象直观. 演示效果 ...
- 普通spring jsp+mybatis项目修改为springboot + jsp +mybatis项目
概述 由于公司决定使用spring cloud,但是公司积累了大量的普通的jsp项目,老的项目直接全部修改为springboot成本过高,周期比较长,而且公司业务正在快速拓展,所以需要把之前的老项目修 ...