2021版王道《数据结构》编程题汇总_21年王道数据结构

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上软件测试知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化的资料的朋友,可以戳这里获取

	if(L.data[i]!=x)
	{
		L.data[k]=L.data[i];
		k++;				//不等于x的元素增1
	}
	L.length=k;				//顺序表L的长度等于k;

}


​ 解法二:用k记录顺序表L中等于x的元素个数,边扫描L边统计k,并将不等于x的元素前移k个位置,最后修改L的长度。


​ 本题代码如下:



void del_x_2(Sqlist &l,Elemtype x)
{
int k=0,i=0; //k记录值等于x的元素个数
while(i<L.length)
{
if(L.data[i]==x)
k++;
else
L.data[i-k]=L.data[i]; //当前元素前移k个位置
i++;
}
L.length=L.length-k; //顺序表L的长度递减
}


##### 4


4.从有序顺序表中删除其值在给定值s与t之间(要求s<t)的所有元素,如果s或t不合理或顺序表为空,则显示出错信息并退出运行。


**注意**:本题与上一题的区别。因为是有序表,所以删除的元素必然是相连的整体。


​ 算法思想:先寻找值大于等于s的第一个元素(第一个删除的元素),然后寻找值大于t的第个元素(最后一个删除的元素的下一个元素),要将这段元素删除,只需直接将后面的元素前移


​ 本题代码如下:



bool Del_s_t2(SqList &L,ElemType s, ElemType t)
{
//删除有序表L中值在给定值s与t之间的所有元素
int i,j;
if(s>=t||L.length==0)
return false;
for(i=0;i<L.length&&L.data[i]<s;i++);//寻找大于等于s的第一个元素
if(i>=L.length)
return false; //所有元素均小于s,返回
for(j=i;j<L.length&&L.data[j]<=t;j++)//寻找值大于t的第一个元素
for(;j<L.length;i++,j++)
L.data[i]=L.data[j]; //前移,填补被删除元素位置
L.length=i;
return true;
}


##### 5


5.从顺序表中删除其值在给定值s与t之间(包含s和t,要求s<t)的所有元素,如果s或t不合理或顺序表为空,则显示出错信息并退出运行


算法思想:从前向后扫描顺序表L,用k记录下元素值在s到t之间元素的个数(初始时k=0).对于当前扫描的元素,若其值不在s到t之间,则前移k个位置;否则执行k++.由于这样每个不在s到t之间的元素仅移动一次,所以算法效率高.


本题代码如下:



bool Del_s_t(SqList &L, ElemType s, ElemType t){
//删除顺序表L中值在给定值s与t之间(要求s<t)的所有元素
int i, k=0;
if(Llength==0||s>=t)
return false; //线性表为空或s、t不合法,返回
for(i=0;i<L length i++){
if(L data[i]>=s&&L data[i]<=t)
k++;
else
L.data[i-k]=L.data[i]; //当前元素前移k个位置

}//for 
L, length-=k;				//长度减小
return true;

}


注意:本题也可从后向前扫描顺序表,每遇到一个值在s到t之间的元素,则删除该元素,其后的所有元素全部前移.但移动次数远大于前者,效率不够高.


##### 6


6.从有序顺序表中删除所有其值重复的元素,使表中所有元素的值均不同


算法思想:注意是有序顺序表,值相同的元素一定在连续的位置上,用类似于直接插入排序的思想,初始时将第一个元素视为非重复的有序表.之后依次判断后面的元素是否与前面非重复有序表的最后一个元素相同,若相同则继续向后判断,若不同则插入到前面的非重复有序表的最后,直至判断到表尾为止.


本题代码如下:



bool. Delete Same(SeqList& L){
if (L.length==0)
return fals;
int i,j; //i存储第一个不相同的元素,j为工作指针
for (1-0,j=1:j<L, length:j++)
if(L.data[i]!=L,data[j]) //查找下一个与上个元素值不同的元素
L.data[++i]=L.data[j]; //找到后,将元素前移
L.length=i+1;
return true;
}


##### 7


7.将两个有序顺序表合并为一个新的有序顺序表,并由函数返回结果顺序表。


算法思想:首先,按顺序不断取下两个顺序表表头较小的结点存入新的顺序表中.然后,看哪个表还有剩余,将剩下的部分加到新的顺序表后面.


本题代码如下:


注意:本算法的方法非常典型,需牢固掌握.



bool Merga(SeqList A, SeqList B, SeqList &C){
//将有序顺序表A与B合并为一个新的有序顺序表C
if(A.length+B, length>C.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) //还剩一个没有比较完的顺序表while(j<B length)
C.data[k++]=B.data[j++]
C.length=k;
return true;
}


##### 8


8.已知在一维数组A[m+n]中依次存放两个线性表(a1,a2,a3,…,am)和(b1,b2,b3,…,bn)。试编写一个函数,将数组中两个顺序表的位置互换,即将(b1,b2b3,…,bn)放在(a1,a2a3,…,an的前面。


算法思想:先将数组A[m+n]中的全部元素(a1,a2a3…,am,b1,b2b3;…,bn)原地逆置为(bnbn-1, n2,",D1,m,m-1,am-2, a1),再对前n个元素和后m个元素分别使用逆置算法,即可得到(b,b2, b3,…,bn、a1,a2,a3,…,an),从而实现顺序表的位置互换.


本题代码如下:



typedef int DataType;
void Reverse(DataType A[],int left, int right, int arraysize){
//逆转(a1eft, aleft+1, aleft+2… aright)为( aright, aright-1,…, aleft)
if (left>=righti lright>=arraysize)
return
int mid=(left+right)/2i
for(int 1=0ii<=mid-leftii++){
Datatype temp=A[left+i];
A[left+i]=A[right-i]; A[right-i]=temp
}
}
void Exchange(DataType A[, int m, int n, int arraysize){
/*数组A[m+n]中,从0到m-1存放顺序表(a1,a2,a3,…,am),从m到m+n-1存放顺序表
(b1,b2,b3…,bn),算法将这两个表的位置互换*/
Reverse(A, 0, m+n-1, arraysize);
Reverse(A, 0, n-l, arraysize);
Reverse(A, n, m+n-l, arraysize);
}


##### 9


9.线性表(a1a2a,…,an)中的元素递增有序且按顺序存储于计算机内。要求设计一算法,完成用最少时间在表中查找数值为x的元素,若找到则将其与后继元素位置相交换,若找不到则将其插入表中并使表中元素仍递增有序


算法思想:顺序存储的线性表递增有序,可以顺序査找,也可以折半査找.题目要求"用最少的时间在表中查找数值为x的元素",这里应使用折半查找法


本题代码如下:



void SearchExchangeInsert(ElemType A[], ElemType x){
int low=0, high=n-1, mid; //1ow和high指向顺序表下界和上界的下标
while(low<=high){
mid=(low+high)/2; //找中间位置
if(A[mid]==x) break; //找到x,退出 while循环
else if(A[mid]<x) low=mid+1; //到中点mid的右半部去查
else high=mid-1; //到中点mid的左半部去查
}//下面两个if语句只会执行一个
if(A[mid]==x&&mid!=n-1){ //若最后一个元素与x相等,
//则不存在与其后继交换的操作
t=A[mid]; A[mid]=A[mid+l]; A[mid+l]=t;
}
if(low>high){ //查找失败,插入数据元素
for(i=n-1;i>high;i–) A[i+1]=A[i]; //后移元素
A[i+1]=x; //插入x
} //结束插入
}


本题的算法也可写成三个函数:查找函数、交换后继函数与插入函数.写成三个函数的优点是逻辑清晰、易读.


##### 10


10.【2010统考真题】设将n(n>1)个整数存放到一维数组R中。设计一个在时间和空间两方面都尽可能高效的算法。将R中保存的序列循环左移p(0<p<n)个位置,即将R中的数据由(X0,X1…,Xn-1变换为(Xp,Xp+1,…,Xn-1,X0,X1,…,Xp-1).要求:


1)给出算法的基本设计思想


2)根据设计思想,采用C或C艹或JaⅦa语言描述算法,关键之处给出注释。


3)说明你所设计算法的时间复杂度和空间复杂度


解答:


1)算法的基本设计思想:可将这个问题视为把数组ab转换成数组ba(a代表数组的前p个元素,b代表数组中余下的n-p个元素),先将a逆置得到a-1b,再将b逆置得到a-1b-1,最后将整个a-1b-1逆置得到(a-1b-1)-1=ba.设 Reverse函数执行将数组元素逆置的操作,对abcdefgh向左循环移动3(p=3)个位置的过程如下:


Reverse(0,p-1)得到 cbadefgh


Reverse(p,n-1)得到 cbahgfed


Reverse(0,n-1)得到 defghabc;


注: Reverse中,两个参数分别表示数组中待转换元素的始末位置


2)使用C语言描述算法如下:



void Reverse (int RU, int from, int to){
for(i=0; i<(to-from +1)/2;i++)
{temp=R[from+i];R[from+i]=R[to-il;R[to-i]=temp;}
}
void Converse(int R[], int n, int p){
Reverse(R,0, p-1);
Reverse(R,p, n-1);
Reverse(R,0, n-1);
}


3)上述算法中三个 Reverse函数的时间复杂度分别为O(p/2)、O(n-p)/2)和O(n/2),故所设计的算法的时间复杂度为O(n),空间复杂度为O()


另解,借助辅助数组来实现.算法思想:创建大小为p的辅助数组S,将R中前p个整数依次暂存在S中,同时将R中后n-p个整数左移,然后将S中暂存的p个数依次放回到R中的后续单元.时间复杂度为O(n),空间复杂度为O§


##### 11


11.【2011统考真题】一个长度为L(L21)的升序序列S,处在第「L2个位置的数称为S的中位数。例如,若序列S1=(1l,13,15,17,19),则S1的中位数是15,两个序列的中位数是含它们所有元素的升序序列的中位数。例如,若S2=(2,4,6,8,20),则S1和S2的中位数是11现在有两个等长升序序列A和B,试设计一个在时间和空间两方面都尽可能高效的算法,找出两个序列A和B的中位数。要求:


1)给出算法的基本设计思想


2)根据设计思想,采用C或++或Java语言描述算法,关键之处给出注释。


3)说明你所设计算法的时间复杂度和空间复杂度


解答:


1)算法的基本设计思想如下.


分别求两个升序序列A、B的中位数,设为a和b,求序列A、B的中位数过程如下:


① a=b,则a或b即为所求中位数,算法结束.


② a<b,则舍弃序列A中较小的一半,同时舍弃序列B中较大的一半,要求两次舍弃的长度相等


③若a>b,则舍弃序列A中较大的一半,同时舍弃序列B中较小的一半,要求两次舍弃的长度相等在保留的两个升序序列中,重复过程①、②、③,直到两个序列中均只含一个元素时为止,较小者即为所求的中位数.


2)本题代码如下:



int M Search(int A[], int b[],int n)
{
int s1=0,d1=n-1,m1,s2=0,d2=n-1,m2;
//分别表示序列A和B的首位数、末位数和中位数
whi1e(s1!=d1|s2!=d2)
{
m1=(s1+d1)/2;
m2=(s2+d2)/2;
if(A[m1]==B[m2])
return AIml] //满足条件①
if(A[m1]<B[m2]) //满足条件②
{
if((s1+d1)82=0) //若元素个数为奇数
{
s1=m1; //舍弃A中间点以前的部分且保留中间点
d2=m2; //舍弃B中间点以后的部分且保留中间点
}
else( //元素个数为偶数
s1=m1+1; //舍弃A中间点及中间点以前部分
d2=m2; //舍弃B中间点以后部分且保留中间点
}
}
else( //满足条件③
if((s2+d2)2=0) //若元素个数为奇数
{
d1=m1 //含弃A中间点以后的部分且保留中间点
S2=m2 //舍弃B中间点以前的部分且保留中间点
}
else{ //元素个数为偶数
d1=m1; //舍弃A中间点以后部分且保留中间点
s2=m2+1; //舍弃B中间点及中间点以前部分
}
}
}
return A[s1]<B[s2]?A[s1]:B[s2];
}


3)算法的时间复杂度为O(log2n),空间复杂度为O(1).


##### 12


12.【2013统考真题】上知一个整数序列A=(a0,a1…,an-1),其中0≤ai<n(0≤1<n)若存在ap1=ap2=…=apm=x且m>n/2(0≤pk<n,1≤k≤m)则称x为A的主元素。例如A=(0,5,5,3,5,7,5,5),则5为主元素;又如A=(0,5,5,3,5,1,5,7),则A中没有主元素。假设A中的n个元素保存在一个一维数组中,请设计一个尽可能高效的算法,找出A的主元素。若存在主元素,则输出该元素;否则输出-1.要求:


1)给出算法的基本设计思想


2)根据设计思想,采用C或C++或Java语言描述算法,关键之处给出注释。


3)说明你所设计算法的时间复杂度和空间复杂度。


解答:


1)给出算法的基本设计思想:算法的策略是从前向后扫描数组元素,标记出一个可能成为主元素的元素Num。然后重新计数,确认Num是否是主元素。


算法可分为以下两步:


① 取候选的主元素。依次扫描所给数组中的每个整数,将第一个遇到的整数Num保存到c中,记录Num的出现次数为1;若遇到的下一个整数仍等于Num,则计数加1,否则计数减1;当计数减到0时,将遇到的下一个整数保存到c中,计数重新记为1,开始新一轮计数,即从当前位置开始重复上述过程,直到扫描完全部数组元素。


② 判断c中元素是否是真正的主元素。再次扫描该数组,统计c中元素出现的次数,若大于n/2,则为主元素;否则,序列中不存在主元素


2)算法实现如下:



img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上软件测试知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化的资料的朋友,可以戳这里获取

判断c中元素是否是真正的主元素。再次扫描该数组,统计c中元素出现的次数,若大于n/2,则为主元素;否则,序列中不存在主元素

2)算法实现如下:



[外链图片转存中...(img-0YiK1vnS-1715706021871)]
[外链图片转存中...(img-z3SevUQX-1715706021871)]
[外链图片转存中...(img-xd3el00V-1715706021872)]

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上软件测试知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[需要这份系统化的资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618631832)**

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值