考研复习,整理下数据结构的一些知识,先从线性表开始吧
主要就是上一些线性表相关的基础算法和基础操作
//线性表结构体声明
typedef struct{
int data[maxSize];
int length;
}sqList;
//插入操作
bool listInsert(sqList& L,int i,int e)//第i个位置插入元素e
{
if(i<0||i>length+1||L.length>=maxSize)//注意插入后不能超过maxSize
return false;
else
{
for(int j=L.length;j>=i;j--)//循环条件的判断抓住第一个移动的元素下标和最后一个移动的元素下标
L.data[j]=L.data[j-1];
L.data[i-1]=e;
}
L.length++;
return true;
}
//删除操作操作
bool listDelete(sqList& L,int i,int& e)//删除的元素为引用遮掩可以在函数外得到e;
{
if(i<1||i>L.length)
return false;
e=L.data[i-1];
for(int j=i-1;j<L.length-1;j++)
L.data[j]=L.data[j+1];
L.length--;
return true;
}
//查找操作,返回其位序则为i+1,返回下表则为i
int locateElem(sqList& L,int e){
for(int i=0;i<L.length;i++)
if(L.data[i]==e)
return i+1;
return 0;
}
//顺序表简单算法设计题
//1.元素逆置
bool reverse(sqList& L)
{
int i=0,j=sqList.length-1;
int temp;
while(i<j){
temp=L.data[i];
L.data[i]=L.data[j];
L.data[j]=temp;
i++;j--;
}
return true;
}
//2.删除所有值为x的元素(注意为了保持连贯性需要移动元素)
bool delete _x_1(sqList& L,int x)
{
int k=0;
for(int i=0;i<L.length;i++)
{
if(L.data[i]!=x)
{
k++;
L.data[k-1]=x;
}
}
L.length=k;
return true;
}
bool delete_x_2(sqList&L,int x)
{
int k=0;
for(int i=0;i<L.length;i++){
if(L.data[i]==x)
k++;
else
L.data[i-k]=L.data[i];
}
L.length-=k;
return true;
}
//这两个方法本质一样,第一种就是非x元素出现的时候它位序是n,下标就是n-1;第二种是非x元素出现的时候它前面出现个n个x下标就减小n
//有序顺序表中删除值重复的元素
bool delete_copy(sqList& L)//该方法自己写的,较为繁琐,应该使用插入排序的思想,如delete_copy_2
{
if(L.length<1)return false;
int x,k=0;
for(int i=0;i<L.length;i++){
if(i==0)x=L.data[i];
L.data[i-k]=L.data[i];
else{
if(L.data[i]==x){
k++;
}
else
x=L.data[i];
}
}
return true;
}
//更优雅高效的方法
void delete_copy_2(sqList& L)
{
if(L.length<1)return false;
int i=0,j=1;
for(;j<L.length;j++){
if(L.data[i]!=L.data[j])
L.data[++i]=L.data[j];//++i和i--在涉及数组下标运算的时候使用好可以让代码看起来更优雅
}
//当然你以为这样就解决问题了???别忘了更改L.length
L.length=i+1;//i值一直都是插入的那个元素的下标值。所以要+1.
}
//经典问题:两个顺序表合并(从小到大排序)
bool Merge(sqList a,sqList b,sqList&c)
{
if(a.length+b.length>maxSize)
return false;
int i=0,j=0,k=0;
//这个就充分体现了下标处使用++符号的好处,可以减少很多的代码行,相似的例子还有两个字符串合并
while(i<a.length&&j<b.length)
{
if(a.data[i]<b.data[j])
c.data[k++]=a.data[i++];
else
c.data[k++]=b.data[j++];
}
while(i<a.length)
c.data[k++]=a.data[i++]
while(j<b.length)
c.data[k++]=b.data[j++];
c.length=k;
return true;
}
//将一个数组元素左移动p位中X0,X1,X2……Xn-1变为Xp,Xp+1,Xp+2……Xn-1,X0,X1……Xp-1(对字符串逆置的很好应用)
//时间复杂度O(n),空间复杂度O(1);
//也可以借助辅助数组来实现,时间复杂度O(n),空间复杂度O(p);
void Reverse(sqList& L,int i,int j)//i,j为下标
{
int temp;
while(i<j){
temp=L.data[i];
L.data[i]=L.data[j];
L.data[j]=L.data[i];
i++;j--
}
}
void converse(sqList& L,int p)
{
int n=L.length;
Reverse(L,0,p-1);
Reverse(L,p,n-1);
Reverse(L,0,n-1)
}
//主元素问题,一个数组中有n个数,出现次数>n/2以上的数称为主元素,这道题目有意思,不过限定条件必须是出现次数大于n/2才可以
//以后还会继续研究其他条件下的这类问题
int Majority(int A[],int n)
{
int cnt=1;//假设第一个元素就是主元素
int x=A[0];
for(int i=1;i<n;i++)
{
if(A[i]==x)cnt++;
else
{
cnt--;
if(cnt<1){
x=A[i];
cnt=1;
}
}
}
cnt=0;
for(int i=0;i<n;i++)
if(A[i]==x)
cnt++;
if(cnt>n/2)
return x;
else return -1
}