数据结构上机题
Position BinarySearch( List L, ElementType X )
{
int l,r,mid;
l=1;
r=L->Last;//注意这里L不要写成l
while(l<=r)
{
mid=(l+r)/2;
if(L->Data[mid]<X) l=mid+1;//这里Data不要写成data
else if(L->Data[mid]>X) r=mid-1;
else return mid;
}
return NotFound;
}
习题1.9 有序数组的插入
、
注释的几个需要注意的点要养成一下习惯
bool Insert(List L,ElementType X)
{
if(L->Last==MAXSIZE-1) return false;
for(int i=0;i<=L->Last;i++)//这里是<=
{
if(L->Data[i]==X) return false;
//从大到小遍历,遍历到第一个比它小的时候就往后挪
else if(L->Data[i]<X)
{
for(int j=L->Last;j>=i;j--)
{
L->Data[j+1]=L->Data[j];//这里别写成i
}
L->Data[i]=X;
L->Last++;//每一次插入成功后记得增加长度
break;
}else{
//如果每一个都大于该值,插入末尾
if(i==L->Last){
L->Data[i+1]=X;
L->Last++;//同理
break;
}
}
}
return true;
}
List Insert(List L,ElementType X)
{
//这种方法是直接找第一个比它的结点的前驱结点
List s=(List)malloc(sizeof (List));
s->Data=X;
List p=L;//工作指针
while( p->Next && X > p->Next->Data)//x比下一个结点的值大才更新指针
//这样保证p指向的就是所需要的前驱结点
{
p=p->Next;
}
s->Next=p->Next;
p->Next=s;
return L; //别忘记返回L
}
List Insert(List L,ElementType X)
{
//这种方法是找第一个大于X的结点
List s,p=L->Next,pre=L;//p为工作指针
s=(List)malloc(sizeof(List));//临时结点放x
s->Data=X;
while(p!=NULL &&p->Data<X){
pre=p;
p=p->Next;
}
if(p!=NULL)
{
pre->Next=s;
s->Next=p;
}
else {
pre->Next=s;
s->Next=NULL;
}
return L;
}
List Merge(List L1,List L2)
{
List p1=L1->Next;
List p2=L2->Next;
//创建一个新的头结点
List L=(List)malloc(sizeof(List));
List p=L;//工作指针p,用来添加L的后续结点
while(p1&&p2)
{
if(p1->Data <p2->Data)
{
//p要移动 p1也要移动
p->Next=p1;
p=p->Next;
p1=p1->Next;
}else{
p->Next=p2;
p=p->Next;
p2=p2->Next;
}
}
//把没接完的链表结点继续接上
if(p1!=NULL){
//只需要把这个最后的跟剩下的连起来即可
p->Next=p1;
}
if(p2!=NULL) p->Next=p2;
//记得把这两个头结点取下来
L1->Next=NULL;
L2->Next=NULL;
return L;
}
实例1.1 最大子列和问题
因为我们只需要得到最大的子列和,那么当sum>0时,不断的去取一个最大值,当sum<0时重新更新sum=0即可,这个最大值便是最大的子列和
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin>>n;
int maxx=-1,sum=0;
for(int i=0;i<n;i++)
{
int x;
cin>>x;
if(sum+x<0) sum=0;
else{
sum+=x;
maxx=max(sum,maxx);
}
}
cout<<maxx;
}
习题2.1 简单计算器
简单是简单,但是注意输入的顺序,不然容易卡半天
#include<bits/stdc++.h>
using namespace std;
int main()
{
int sum=0;
char op;
cin>>sum>>op;
while(op!='=')
{
int x;
cin>>x;//输入操作数
if(op=='+') sum+=x;
else if(op=='-') sum-=x;
else if(op=='*') sum*=x;
else if(op=='/')
{
if(x==0){
cout<<"ERROR";
return 0;
}
else sum/=x;
}else {
cout<<"ERROR";
return 0;
}
cin>>op;//输入符号
}
cout<<sum;
}
习题2.2 数组循环左移
这题其实有三个方法
方法1:直接观察结果输出即可
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n,m;
cin>>n>>m;
m%=n;
vector<int>ve(n+1);
for(int i=1;i<=n;i++) cin>>ve[i];
cout<<ve[m+1];
for(int i=m+2;i<=n;i++) cout<<" "<<ve[i];
for(int i=1;i<=m;i++) cout<<" "<<ve[i];
}
方法2:通过每次将N个元素循环位移一次,进行m次这样的循环位移
#include <bits/stdc++.h>
using namespace std;
int a[105];
void move(int n)
{
int temp=a[0];
for(int i=0;i<n-1;i++) a[i]=a[i+1];
a[n-1]=temp;
}
int main()
{
int n,m;
cin>>n>>m;
m%=n;
for(int i=0;i<n;i++) cin>>a[i];
for(int i=0;i<m;i++) move(n);
cout<<a[0];
for(int i=1;i<n;i++) cout<<" "<<a[i];
}
方法3:就是通过元素翻转位置比如将1 2 3 4 5 6 7 8翻转为3 2 1 4 5 6 7 8然后按照特定顺序输出即可,这里不给出代码。
习题2.3 数列求和-加强版
常规方法是直接进行加减,但是这样当位数太大的时候是会溢出的,所以采取最优的方法就是在每一位上进行计算,然后把对应的每一位存在数组里,最后再输出每一位。原理其实就是加法的进位
#include <bits/stdc++.h>
using namespace std;
#define int long long
signed main()
{
int A,N;
cin>>A>>N;
if(!N){
cout<<0;
return 0;
}
int S[100005];
memset(S,0,sizeof S);
int c=0;//每一位上的进位
for(int i=0;i<N;i++)
{
//加法的进位
c+=A*(N-i);
S[i]=c%10;
c/=10;
}
//最高位如果不是0
if(c) cout<<c;
//倒序输出
for(int i=N-1;i>=0;i--) cout<<S[i];
}
习题3.4 最长连续递增子序列
处理两个子问题1.序列最大长度 2.最终的序列区间的左右端点下标
1.只要当\(a[i]<=a[i-1]\)时,我们就去更新当前的最大序列长度,和最终答案的下标即可,开temp,l,r分别来记录当前序列长度、序列当前左端点、序列当前右端点即可,否则temp++,r++
2.注意特别处理一下如果序列直接到达了末尾这种情况
#include <bits/stdc++.h>
using namespace std;
int a[100005];
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
int ansl=0,ansr=0,maxx=-1,l=1,r=0;//l记得从1开始
int temp=1;//当前序列长度
for(int i=1;i<=n;i++)
{
if(a[i]>a[i-1])
{
temp++;
r++;
}else{
if(temp>maxx)//如果当前序列长度大于最大的长度
{
maxx=temp;
ansl=l;//更新答案区间下标
ansr=r;
}
temp=1;
l=r=i;
}
}
//如果这个序列到达了末尾还需要处理一下
if(temp>maxx){
maxx=temp;
ansl=l;
ansr=r;
}
cout<<a[ansl];
for(int i=ansl+1;i<=ansr;i++) cout<<" "<<a[i];
}
基础实验3-2.2 单链表分段逆转
每K段要进行翻转,也就是相当于进行K次头插法,把每一次头插法的第一个结点,当作下一次头插法的头结点。具体可以看图理解手动模拟。
void K_Reverse(List L,int K)
{
List t=L->Next;
int cnt=0;
while(t){
cnt++;
t=t->Next;
}
List head=L,new,old,tmp,s;
//head为每一次头插法的头结点
//s为每一次头插法的第一个结点,也是下一次头插法的头结点
//new 和old用来翻转指针将后一个指向前一个
//tmp 用来往后移动old
for(int i=0;i<cnt/K;i++)
{
new=head->Next;
old=new->Next;
s=new;
int j=K-1;
while(j--)
{
tmp=old->Next;
old->Next=new;
new=old,old=tmp;
}
head->Next=new;
s->Next=old;
head=s;
}
}
posted on 2024-09-02 12:22 swj2529411658 阅读(7) 评论(0) 编辑 收藏 举报