求职系列笔记(1)---数据结构和算法
2016-08-26 19:06
363 查看
数组涉及到的算法相当多,主要分为:排序算法、查找算法等。
(a)二分查找主要有两种,一种是基于除法的,一种基于加减的(也叫:斐波那契查找法、黄金查找法)
/排序算法,主要掌握快排、归并排序、堆排序; 至于其他的冒泡、选择、插入、桶排序等很容易掌握;/
本文继续探讨partition函数的其他应用,这是一种思想,特别重要;
基于快速排序partition思想的算法拓展
(1)输入一个整数数组,调整数组中数字的顺序,使得所有奇数位于数组的前半部分,
所有偶数位于数组的后半部分。要求时间复杂度为O(n)。
(2)荷兰国旗问题:这个问题类似快排中partition过程,
只是需要用到三个指针:一个前指针begin,一个中指针current,一个后指针end,
current指针遍历整个数组序列,当
(a)current指针所指元素为0时,与begin指针所指的元素交换,而后current++,begin++;
(b)current指针所指元素为1时,不做任何交换(即球不动),而后current++;
(c)current指针所指元素为2时,与end指针所指的元素交换,而后,current指针不动,end–;
关于这部分,可以参考如下:
(1)奇偶调序 http://taop.marchtea.com/02.06.html
(2)荷兰国旗 http://taop.marchtea.com/02.07.html
继续学习其他排序算法,归并排序
/*
思考,归并排序时间复杂度o(n*logn),稳定排序,消耗o(n)空间复杂度;
参考《剑指offer》中数组中的逆序对,也是采用归并排序的方法。
参考代码如下:
*/
数组在其他的应用,如用一个数组实现三个栈;
参考代码如下:
数组的排序算法中,主要讲了快排、归并排序,这两个排序的思想应用广泛。至于其他排序,可以自行学习。
总结,数组是一种最常用的数据结构,在动态规划中、在回溯法中进行修枝中也起到很大重要。详见下一期内容;
(a)二分查找主要有两种,一种是基于除法的,一种基于加减的(也叫:斐波那契查找法、黄金查找法)
/*二分查找的算法如下(1):*/ int binarySearch(int arr[],int n,int value)//查找区间为[0,n-1] { int low=0; int high=n-1; while(low<=high)//这个条件很讲究 { int mid=low+(high-low)>>1; if(arr[mid]<value) low=mid+1; else if(arr[mid]>value) high=mid-1; else return mid;//这个很有讲究,如果放到最后,可以节省很多时间; } return -1;//说明没有查找到 } /*二分查找的算法如下(2):*/ int binarySearch(int arr[],int n,int value)//查找区间为[0,n-1] { int low=0; int high=n-1; while(low<high)//这个条件很讲究 { int mid=low+(high-low)>>1; if(arr[mid]<value) low=mid; else if(arr[mid]>value) high=mid; else return mid;//这个很有讲究,如果放到最后,可以节省很多时间; } return -1;//说明没有查找到 }
/排序算法,主要掌握快排、归并排序、堆排序; 至于其他的冒泡、选择、插入、桶排序等很容易掌握;/
/*快排算法,主要基于递归和快速划分函数partition*/ int partition(int arr[],int low,int high)//划分区间为[low,high] { int temp=arr[low];//找到一个基准点 while(low<high) { while((low<high)&&(arr[high]>temp)) high--; swap(arr[low],arr[high]); while((low<high)&&(arr[low]<=temp)) low++; swap(arr[low],arr[high]); } return low; } void quicksort(int arr[],int low,int high)//n为数组长度 { if(low>=high) return;//条件改为if(low>=high)也可以,因为指向同一个元素,可以不划分; int provit=partition(arr,low,high); quicksort(arr,low,provit-1); quicksort(arr,provit+1,high); }
//思考,快排时间复杂度为o(n*logn),最差情况下为:o(N^2)
本文继续探讨partition函数的其他应用,这是一种思想,特别重要;
基于快速排序partition思想的算法拓展
(1)输入一个整数数组,调整数组中数字的顺序,使得所有奇数位于数组的前半部分,
所有偶数位于数组的后半部分。要求时间复杂度为O(n)。
(2)荷兰国旗问题:这个问题类似快排中partition过程,
只是需要用到三个指针:一个前指针begin,一个中指针current,一个后指针end,
current指针遍历整个数组序列,当
(a)current指针所指元素为0时,与begin指针所指的元素交换,而后current++,begin++;
(b)current指针所指元素为1时,不做任何交换(即球不动),而后current++;
(c)current指针所指元素为2时,与end指针所指的元素交换,而后,current指针不动,end–;
参考代码如下: while( current<=end ) { if( array[current] ==0 ) { swap(array[current],array[begin]); current++; begin++; } else if( array[current] == 1 ) { current++; } else //When array[current] =2 { swap(array[current],array[end]); end--; } }
关于这部分,可以参考如下:
(1)奇偶调序 http://taop.marchtea.com/02.06.html
(2)荷兰国旗 http://taop.marchtea.com/02.07.html
继续学习其他排序算法,归并排序
/*二路归并排序,这个算法应用很广泛,也是稳定算法*/ void mergearray(int a[],int temp[],int first,int mid,int last)//将有二个有序数列a[first...mid]和a[mid...last]合并。 { int i=first, j=mid + 1; int m=mid,n=last; int k=0; while(i<= m && j<= n) { if(a[i]<=a[j]) temp[k++]=a[i++]; else temp[k++]=a[j++]; } while(i<=m) temp[k++]=a[i++]; while(j<=n) temp[k++]=a[j++]; for(i=0;i<k;i++) a[first+i]=temp[i]; } void Merge(int arr[],int copy[],int low,int high)//处理主体函数,递归实现划分、合并 { if(low<high) { int mid=(low+high)>>1; mergesort(arr,copy, low, mid); //左边有序 mergesort(arr, copy,mid + 1,high); //右边有序 mergearray(arr,copy,low,mid,high); //再将二个有序数列合并 } } void Mergesort(int arr[],,int low,int high)//调用接口函数; { int* copy=new int[]; b4e8 Merge(arr,copy,low,high); }
/*
思考,归并排序时间复杂度o(n*logn),稳定排序,消耗o(n)空间复杂度;
参考《剑指offer》中数组中的逆序对,也是采用归并排序的方法。
参考代码如下:
class Solution { public: int InversePairs(vector<int> data) { if(data.size()<=1) return 0; int* copy=new int[data.size()]; //初始化数组 for(unsigned int i=0;i<data.size();i++) copy[i]=0; int count=InversePairCore(data,copy,0,data.size()-1); delete[] copy; return count; } int InversePairCore(vector<int>& data,int*& copy,int start,int end) { if(start==end) { copy[start]=data[start]; return 0; } //将数组拆分成两部分 int length=(end-start)/2; //分别计算左边部分和右边部分 int left=InversePairCore(data,copy,start,start+length); int right=InversePairCore(data,copy,start+length+1,end); //进行逆序计算 int i=start+length; int j=end; int index=end; int count=0; while(i>=start && j>=start+length+1) { if(data[i]>data[j]) { copy[index--]=data[i--]; //统计长度 count+=j-start-length; } else { copy[index--]=data[j--]; } } for(;i>=start;--i) { copy[index--]=data[i]; } for(;j>=start+length+1;--j) { copy[index--]=data[j]; } //排序 for(int i=start; i<=end; i++) { data[i] = copy[i]; } //返回最终的结果 return (count+left+right); } };
*/
数组在其他的应用,如用一个数组实现三个栈;
参考代码如下:
class stack3{ public: stack3(int size = 300){ buf = new int[size*3]; ptop[0]=ptop[1]=ptop[2]=-1;//三个栈底分别指向-1 this->size = size; } ~stack3(){ delete[] buf; } void push(int stackNum, int val)//stackNum为0,1,2分别代表栈 { int idx = stackNum*size + ptop[stackNum] + 1;//求出栈的 buf[idx] = val; ++ptop[stackNum]; } void pop(int stackNum)//弹栈 { --ptop[stackNum]; } int top(int stackNum)//栈顶元素 { int idx = stackNum*size + ptop[stackNum]; return buf[idx]; } bool empty(int stackNum)//判断栈空 { return ptop[stackNum]==-1; } private: int *buf; int ptop[3]; int size; };
数组的排序算法中,主要讲了快排、归并排序,这两个排序的思想应用广泛。至于其他排序,可以自行学习。
总结,数组是一种最常用的数据结构,在动态规划中、在回溯法中进行修枝中也起到很大重要。详见下一期内容;
相关文章推荐
- 今日笔记系列之Castor
- SCJP认证考试复习笔记系列之一
- Lua入门系列----pil学习笔记之 Type and Values (1)
- Spring项目开发笔记系列(三)
- 李浩学习计算机系列笔记——ADO.NET基础入门
- Spring项目开发笔记系列(四)
- Lua入门系列----pil学习笔记之Type and Values (2)
- 【ajax ASP.NET AJAX入门系列(1):概述】学习笔记
- Spring项目开发笔记系列(二)
- SCJP认证考试复习笔记系列之二
- setup.s (读核笔记系列)
- [学习笔记]Asp.net(C#)菜鸟进级系列之引用类型
- Lua入门系列----pil学习笔记之Getting Start
- 听 Windows Vista 黄金周系列课程(2):WPF(I)-微软下一代图形表现系统 笔记
- SCJP考试认证复习笔记系列之三
- [笔记系列]struts开发中遇到的文本框readonly属性
- bootsect.S (读核笔记系列)
- ASP.NET Forum 学习笔记系列--Web.config
- Spring项目开发笔记系列(六)
- 李浩学习计算机系列笔记——XML学习笔记