您的位置:首页 > 理论基础 > 数据结构算法

求职系列笔记(1)---数据结构和算法

2016-08-26 19:06 363 查看
数组涉及到的算法相当多,主要分为:排序算法、查找算法等。

(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;
};


数组的排序算法中,主要讲了快排、归并排序,这两个排序的思想应用广泛。至于其他排序,可以自行学习。

总结,数组是一种最常用的数据结构,在动态规划中、在回溯法中进行修枝中也起到很大重要。详见下一期内容;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  求职系列笔记-1