提示 他日若是同淋雪 此生亦算共白头
对比
首先无论是静态链表还是动态链表都是需要三个信息,一个是链表中的实际长度Length,一个是最大长度MaxSize,静态的时候是通过在结构体中设置一个数组,判断实际长度Length与其中的最大长度作对比,来判断是否越界,若是在动态链表中 则扩容,
//静态的链表的定义
#define MaxSize 5//注意宏定义是没有标点的
typedef struct{
int array[Maxsize];
int length;
}SqList;
//动态链表的定义
typedef struct{
Elemtype *data;
int lentth;//用来记录数据的长度
int MaxSize;//用来记录数组的容量
}SeqList;
//注意这里是申请一段空间,申请空间的方式有c风格与c++风格
//c风格
SeqList.data=(Elemtype*)malloc(sizeof(Elemtype)*Maxsize);
//c++风格
SeqList.data= ElemType[InitSize];
//释放空间的时候也要注意
/*free是释放由malloc申请的空间*/
free(data)直接就释放了一整串的空间
delete []data;//正确使用的方法
delete data==delete data[0];//则相当于只是释放了一系列空间中的第一个空间
data=NULL;
/*还有一个要注意的就是释放之后要将指针的指向置为NUll
因为后面要使用 就并不知道是否被释放过了*/
注意
插入
若是需要插入元素 ,则需要判断给出的位置是否合理,同样的也需要判断是否空间已满,若是动态已满则需要扩容,若是静态已满,退出即可,假如元素之后别忘了修改其中的Length的数据,尾插法时间复杂度是O(1) 头插法时间复杂度是O(n) 平均时间复杂度是O(n)
删除
同样的道理要是要删除,若是给定的位置信息 同样需要判断位置是否合理,需要判断其中是否有元素,并将其中的Length的长度减一,与插入相同,删除的返回值也是bool类型,与头删尾删的时间复杂度是一样的,也同样的别忘了对其中记录数据长度的Length 进行修改即可
第一题
#include<bits/stdc++.h>
#define MaxSize 5
#define ElemType int
using namespace std;
typedef struct{
ElemType *data=NULL;
int length=0;
int capacity=MaxSize;
}SeqList;
bool InitSql(SeqList &L){
L.data=(int*)malloc(sizeof(int)*MaxSize);
cout<<"请输入你要添加的数值"<<endl;
int input=0;int i=0;
while(scanf("%d",&input)!=EOF){
if(L.length==L.capacity){//需要扩容
cout<<"此时需要扩容"<<endl;
L.data=(int*)realloc(L.data,sizeof(int)*(L.capacity*2));
L.capacity*=2;
}
L.data[L.length++]=input;
}
L.length-=1;
return true;
}
int Solution(SeqList &L){
if(L.length==0){
cout<<"此时链表中没有元素"<<endl;
return 0;
}
int min=L.data[0];int postion=0;
for(int i=0;i<=L.length;i++){
if(min>L.data[i]){
min=L.data[i];
postion=i;
}
}
L.data[postion]=L.data[L.length];
}
void Print(SeqList L){
cout<<"此时的数组是"<<endl;
for(int i=0;i<=L.length;i++){
cout<<L.data[i]<<" ";
}
}
main(){
SeqList L;
InitSql(L);
Solution(L);
Print(L);
}
第二题
思路
就是使用两个指针 一个指向第一个 一个指向最后一个 两个指针的指向一直靠经便可
void swap(int &a,int &b){
a^=b;
b^=a;
a^=b;
}
void Solution2(SeqList &L){
int i=0;//定义一个指针指向第一个坐标
int j=L.length-1;//同样的定义一个指针指向最后一个元素
while(i<j){
swap(L.data[i++],L.data[j--]);
}
}
第三题
思路
也是使用两个指针 一个从前往后找值为x的 一个从后向前找 值不是x的交换两个指针所指向的数值,最后若是两个相遇,判断此时指向的是否是数值为x,第二个思路就是:使用i 来遍历这个数组,使用一个k来确定每一个数移动的次数
void Solution3(SeqList &L){
int elem;int step=0;
cout<<"请输入你要删的值"<<endl;
cin>>elem;
for(int i=0;i<=L.length;i++){
if(L.data[i]==elem){
step++;
}
else L.data[i-step]=L.data[i];
}
L.length-=step;
}
第四题
void Solution4(SeqList &L){
int begin;int end;int step=0;
cout<<"请输入一个数据空间(删除区间在[begin,end]之间的所有数)"<<endl;
cin>>begin;cin>>end;
if(L.length==0||begin>end){
cout<<"你所输入的信息有误"<<endl;
return ;
}
for(int i=0;i<=L.length;i++){
if(L.data[i]>begin&&L.data[i]<end){
step++;
}
else L.data[i-step]=L.data[i];
}
cout<<"此时的step是等于"<<step<<endl;
L.length-=step;
}
第五题
思路
和上面的差不多,就是多了一个筛选条件
void Solution5(SeqList &L){
int begin;int end;int step=0;
cout<<"请输入一个数据空间(删除区间在[begin,end]之间的所有数)"<<endl;
cin>>begin;cin>>end;
if(L.length==0||begin>end){
cout<<"你所输入的信息有误"<<endl;
return ;
}
for(int i=0;i<=L.length;i++){
if(L.data[i]>=begin&&L.data[i]<=end){
step++;
}
else L.data[i-step]=L.data[i];
}
cout<<"此时的step是等于"<<step<<endl;
L.length-=step;
}
第六题
思路
使用快慢指针的方法,使用快指针来进行扫描数组,使用慢指针来表示慢指针之前的数都是有序的
void Solution6(SeqList &L){
int quality=1,slow=1;
for(int quality=1;quality<=L.length;){
if(L.data[quality]==L.data[slow]){
quality+=1;
}
else{
slow+=1;
L.data[slow]=L.data[quality];
quality+=1;
}
}
L.length=slow;
}
第七题
思路
我的第一想法是 使用两个指针分别指向两个数组,再开辟一个新的空间用来存储两个数组合并之后的数组,比较此时指针指向的数字的大小
SeqList* Solution7(){
SeqList L1,L2;
int p=0,q=0,k=0;//定义三个指针
cout<<"请输入第一个数组"<<endl;
InitSql(L1);
cout<<"请输入第二个数组"<<endl;
InitSql(L2);
SeqList *L3=(SeqList*)malloc(sizeof(SeqList)*(L1.length+L2.length+2));
for(int i=0;i<L1.length+L2.length+2;i++){
//需要选取这么多次的数
if(L1.data[p]<=L2.data[q]) {
L3->data[k]=L1.data[p];
k+=1,p+=1;
}
else{
L3->data[k]=L2.data[q];
k+=1,q+=1;
}
}
L3->length=k-1;L3->capacity=k-1;
cout<<"此时的L3的数组是"<<endl;
for(int i=0;i<=L3->length;i++){
cout<<L3->data[i]<<" ";
}
return L3;
}
//本来前面写的都是可执行的结果一下子一不小心给删了 就从第八题重新写一下吧,上面都是运行过的 都是可以执行的
第八题
思路
我的第一想法是,重新建立一个数组,以分界点重新将数组放入进去,但是这个想法太简单了,我们另外的想法就是首先整个数组首尾交换,交换完之后,再分别交换这两个数组的首尾的部分
void Solution8(SeqList &L){
int border;
cout<<"请输入一个分界线(从零开始,包括分界线也交换)"<<endl;
cin>>border;
int p=0,q=L.length;
while(p<q){
swap(L.data[p++],L.data[q--]);
}
//实现整数数组的交换
Print(L);
int k=border,m=border+1;p=0,q=L.length;
while(p<k){
swap(L.data[p++],L.data[k--]);
}
Print(L);
while(m<q){
swap(L.data[m++],L.data[q--]);
}
}
第九题
思路
查找方法有许多种,这里是有序的,并且需要时间较短,这里就使用折半查找
void Solution9(SeqList &L){
int input;
cout<<"请输入你要查找的值"<<endl;
cin>>input;
int from=0,to=L.length,mid=(L.length+0)>>2;
while(from<=to){
if(L.data[mid]<input){
from=mid+1;
mid=from+(to-from)/2;
}
else if(L.data[mid]>input){
to=mid-1;
mid=from+(to-from)/2;
}
else{
cout<<"成功查找"<<endl;
swap(L.data[mid],L.data[mid+1]);
return ;
}
}
cout<<"未存在这个数"<<endl;
//将mid之后的数 依次向后移动一个位置,此时就需要考虑容积什么的
if(L.capacity==L.length+1){
L.data=(int*)realloc(L.data,sizeof(int)*(L.capacity*2));
L.capacity*=2;
}
int i=L.length;
while(i>=mid){
L.data[i+1]=L.data[i];
i--;
}
L.data[mid]=input;
L.length+=1;
}
第十题
思路
你会发现几乎和上面第八题一样,你要是问我不一样之处,目前看来就题目说法不一样
时间复杂度O(n) 空间复杂度O(1)
这里就略。。。。
第11 题
思路
我的第一想法是合并两个数组,从中寻找中位数,但是这样未免太简单,若是解题的话第一种好像见两分,建议第一种方式
王道最后的答案的思想是:两个序列的中位数其实是处于两个序列各自中位数之间 ,那么此时我们在两个序列中划去两边的元素就相当于从序列C 中划去相同数量的大小元素,最后留下的也就是中位数,
int Solution11(){
SeqList L1,L2;
cout<<"请输入一个你要输入的一个数组"<<endl;
InitSql(L1);
cout<<"请输入另外一个你要输入的数组"<<endl;
InitSql(L2);
//找这两个数组的中位数,因为要不停的删减,这里建议使用每一个数都使用
//两个指针,这样删除的时候改变指针的指向就可以达到同样的效果了
int begin1=0,end1=L1.length;int begin2=0,end2=L2.length; int mid1,mid2;
while(begin1!=end1){//当每一个顺序表包含的都是一个元素的时候
mid1=begin1+(end1-begin1)/2;
mid2=begin2+(end2-begin2)/2;
if(L1.data[mid1]==L2.data[mid2]){
cout<<"此时中位数相等 返回"<<endl;
return L1.data[mid1];
}
else if(L1.data[mid1]<L2.data[mid2]){
cout<<"此时比较的是"<<L1.data[mid1]<<"与"<<L2.data[mid2]<<endl;
begin1=mid1;//舍弃L1中比L1.data[mid]小的
end2=mid2; //舍弃L2中比L2.data[mid]大的
}
else{
cout<<"此时比较的是"<<L1.data[mid1]<<"与"<<L2.data[mid2]<<endl;
end1=mid1;//舍弃L1中比L1.data[mid]大的
begin2=mid2;//舍弃L2中比L2.data[mid]小的
}
}
//此时两个顺序表中都是只用一个元素 从中选取一个最小的放回就可以
return L1.data[mid1]<L2.data[mid2]? L2.data[mid2]: L1.data[mid1];
}
运行结果
十二题
思想
我的第一个想法是,使用一个个桶来装数值,最后再来统计每一个桶中数 判断是否有一个超过n/2;
王道上给的方法是选取一个候选元素,遍历数组 若是与候选主元素相同则count++ t若是与候选主元素不同count-- 当count==0 的时候下一个出现的重新定位候选主元素,注意不能通过最后count的值来判断是否一定存在主元素 最后还需要经过一次遍历,来判断此时的候补主元素是否的确是主元素
第三个也是最简单的一个就是遍历每一个数,判断是否>n/2
void Solution12(SeqList &L){
int count=0;int k=0;
for(int i=0;i<=L.length;i++){
if(L.data[i]==L.data[k]){
count++;
}
else count--;
if(0==count){
k=i;
count++;
}
}
count=0;
for(int i=0;i<=L.length;i++){
if(L.data[k]==L.data[i])
count++;
}
if(count>(L.length+1)/2){
cout<<"此时数组中的主元素是"<<L.data[k]<<endl;
}
else cout<<"不存在主元素"<<endl;
}
13 题
思路
我的第一个思路是先进行排序,排序之后 设置一个flag 再来找是否发生改变
第二个方法相当与涂色, 设置两个数组,若是在数组中发现了数,则将flag[]=false;当一遍扫描完成再来扫描第一个出现的flag[]==true的就是最小的
void Solution13(SeqList &L){
bool flag[L.length+3]={0};//设置这么大的空间足够,因为大于这个空间的值不必考虑,负数也不必考虑 为什么+3 因为第一个空间不用,最后一个也不用,length 本来就空间从零开始 所以加三
for(int i=0;i<=L.length;i++){
if(L.data[i]>0&&L.data[i]<=L.length+1){
flag[L.data[i]]=true;
}
}
for(int i=1;i<L.length+3;i++){
if(!flag[i]){
cout<<"此时的最小值是"<<i<<endl;
return;
}
}
}
代码汇总
#include<bits/stdc++.h>
#define MaxSize 5
#define ElemType int
using namespace std;
typedef struct{
ElemType *data=NULL;
int length=0;
int capacity=MaxSize;
}SeqList;
bool InitSql(SeqList &L){
L.data=(int*)malloc(sizeof(int)*MaxSize);
cout<<"请输入你要添加的数值"<<endl;
int input=0;int i=0;
while(scanf("%d",&input)!=EOF){
if(L.length==L.capacity){//需要扩容
cout<<"此时需要扩容"<<endl;
L.data=(int*)realloc(L.data,sizeof(int)*(L.capacity*2));
L.capacity*=2;
}
L.data[L.length++]=input;
}
L.length-=1;
return true;
}
int Solution1(SeqList &L){
if(L.length==0){
cout<<"此时链表中没有元素"<<endl;
return 0;
}
int min=L.data[0];int postion=0;
for(int i=0;i<=L.length;i++){
if(min>L.data[i]){
min=L.data[i];
postion=i;
}
}
L.data[postion]=L.data[L.length];
}
void Print(SeqList L){
cout<<"此时的数组是"<<endl;
for(int i=0;i<=L.length;i++){
cout<<L.data[i]<<" ";
}
cout<<endl;
}
void swap(int &a,int &b){
a^=b;
b^=a;
a^=b;
}
void Solution2(SeqList &L){
int i=0;//定义一个指针指向第一个坐标
int j=L.length-1;//同样的定义一个指针指向最后一个元素
while(i<j){
swap(L.data[i++],L.data[j--]);
}
}
void Solution3(SeqList &L){
int elem;int step=0;
cout<<"请输入你要删的值"<<endl;
cin>>elem;
for(int i=0;i<=L.length;i++){
if(L.data[i]==elem){
step++;
}
else L.data[i-step]=L.data[i];
}
L.length-=step;
}
void Solution4(SeqList &L){
int begin;int end;int step=0;
cout<<"请输入一个数据空间(删除区间在[begin,end]之间的所有数)"<<endl;
cin>>begin;cin>>end;
if(L.length==0||begin>end){
cout<<"你所输入的信息有误"<<endl;
return ;
}
for(int i=0;i<=L.length;i++){
if(L.data[i]>begin&&L.data[i]<end){
step++;
}
else L.data[i-step]=L.data[i];
}
cout<<"此时的step是等于"<<step<<endl;
L.length-=step;
}
void Solution5(SeqList &L){
int begin;int end;int step=0;
cout<<"请输入一个数据空间(删除区间在[begin,end]之间的所有数)"<<endl;
cin>>begin;cin>>end;
if(L.length==0||begin>end){
cout<<"你所输入的信息有误"<<endl;
return ;
}
for(int i=0;i<=L.length;i++){
if(L.data[i]>=begin&&L.data[i]<=end){
step++;
}
else L.data[i-step]=L.data[i];
}
cout<<"此时的step是等于"<<step<<endl;
L.length-=step;
}
void Solution6(SeqList &L){
int quality=1,slow=1;
for(int quality=1;quality<=L.length;){
if(L.data[quality]==L.data[slow]){
quality+=1;
}
else{
slow+=1;
L.data[slow]=L.data[quality];
quality+=1;
}
}
L.length=slow;
}
SeqList* Solution7(){
SeqList L1,L2;
int p=0,q=0,k=0;//定义三个指针
cout<<"请输入第一个数组"<<endl;
InitSql(L1);
cout<<"请输入第二个数组"<<endl;
InitSql(L2);
SeqList *L3=(SeqList*)malloc(sizeof(SeqList)*(L1.length+L2.length+2));
for(int i=0;i<L1.length+L2.length+2;i++){
//需要选取这么多次的数
if(L1.data[p]<=L2.data[q]) {
L3->data[k]=L1.data[p];
k+=1,p+=1;
}
else{
L3->data[k]=L2.data[q];
k+=1,q+=1;
}
}
L3->length=k-1;L3->capacity=k-1;
cout<<"此时的L3的数组是"<<endl;
for(int i=0;i<=L3->length;i++){
cout<<L3->data[i]<<" ";
}
return L3;
}
void Solution8(SeqList &L){
int border;
cout<<"请输入一个分界线(从零开始,包括分界线也交换)"<<endl;
cin>>border;
int p=0,q=L.length;
while(p<q){
swap(L.data[p++],L.data[q--]);
}
//实现整数数组的交换
Print(L);
int k=border,m=border+1;p=0,q=L.length;
while(p<k){
swap(L.data[p++],L.data[k--]);
}
Print(L);
while(m<q){
swap(L.data[m++],L.data[q--]);
}
}
void Solution9(SeqList &L){
int input;
cout<<"请输入你要查找的值"<<endl;
cin>>input;
int from=0,to=L.length,mid=(L.length+0)>>2;
while(from<=to){
if(L.data[mid]<input){
from=mid+1;
mid=from+(to-from)/2;
}
else if(L.data[mid]>input){
to=mid-1;
mid=from+(to-from)/2;
}
else{
cout<<"成功查找"<<endl;
swap(L.data[mid],L.data[mid+1]);
return ;
}
}
cout<<"未存在这个数"<<endl;
//将mid之后的数 依次向后移动一个位置,此时就需要考虑容积什么的
if(L.capacity==L.length+1){
L.data=(int*)realloc(L.data,sizeof(int)*(L.capacity*2));
L.capacity*=2;
}
int i=L.length;
while(i>=mid){
L.data[i+1]=L.data[i];
i--;
}
L.data[mid]=input;
L.length+=1;
}
int Solution11(){
SeqList L1,L2;
cout<<"请输入一个你要输入的一个数组"<<endl;
InitSql(L1);
cout<<"请输入另外一个你要输入的数组"<<endl;
InitSql(L2);
//找这两个数组的中位数,因为要不停的删减,这里建议使用每一个数都使用
//两个指针,这样删除的时候改变指针的指向就可以达到同样的效果了
int begin1=0,end1=L1.length;int begin2=0,end2=L2.length; int mid1,mid2;
while(begin1!=end1){//当每一个顺序表包含的都是一个元素的时候
mid1=begin1+(end1-begin1)/2;
mid2=begin2+(end2-begin2)/2;
if(L1.data[mid1]==L2.data[mid2]){
cout<<"此时中位数相等 返回"<<endl;
return L1.data[mid1];
}
else if(L1.data[mid1]<L2.data[mid2]){
cout<<"此时比较的是"<<L1.data[mid1]<<"与"<<L2.data[mid2]<<endl;
begin1=mid1;//舍弃L1中比L1.data[mid]小的
end2=mid2; //舍弃L2中比L2.data[mid]大的
}
else{
cout<<"此时比较的是"<<L1.data[mid1]<<"与"<<L2.data[mid2]<<endl;
end1=mid1;//舍弃L1中比L1.data[mid]大的
begin2=mid2;//舍弃L2中比L2.data[mid]小的
}
}
//此时两个顺序表中都是只用一个元素 从中选取一个最小的放回就可以
return L1.data[mid1]<L2.data[mid2]? L2.data[mid2]: L1.data[mid1];
}
void Solution12(SeqList &L){
int count=0;int k=0;
for(int i=0;i<=L.length;i++){
if(L.data[i]==L.data[k]){
count++;
}
else count--;
if(0==count){
k=i;
count++;
}
}
count=0;
for(int i=0;i<=L.length;i++){
if(L.data[k]==L.data[i])
count++;
}
if(count>(L.length+1)/2){
cout<<"此时数组中的主元素是"<<L.data[k]<<endl;
}
else cout<<"不存在主元素"<<endl;
}
void Solution13(SeqList &L){
bool flag[L.length+3]={0};//设置这么大的空间足够,因为大于这个空间的值不必考虑,复数也不必考虑
for(int i=0;i<=L.length;i++){
if(L.data[i]>0&&L.data[i]<=L.length+1){
flag[L.data[i]]=true;
}
}
for(int i=1;i<L.length+3;i++){
if(!flag[i]){
cout<<"此时的最小值是"<<i<<endl;
return;
}
}
}
void Menu(){
int choice;
cout<<"请问你要解决第几题";
cin>>choice;
switch(choice){
case 1:{
SeqList L;
InitSql(L);
Solution1(L);
Print(L);
break;
}
case 2:{
SeqList L;
InitSql(L);
Solution2(L);
Print(L);
break;
}
case 3:{
SeqList L;
InitSql(L);
Solution3(L);
Print(L);
break;
}
case 4:{
SeqList L;
InitSql(L);
Solution4(L);
Print(L);
break;
}
case 5:{
SeqList L;
InitSql(L);
Solution5(L);
Print(L);
break;
}
case 6:{
SeqList L;
InitSql(L);
Solution6(L);
Print(L);
break;
}
case 7:{
Solution7();
break;
}
case 8:{
SeqList L;
InitSql(L);
Solution8(L);
Print(L);
break;
}
case 9:{
SeqList L;
InitSql(L);
Solution9(L);
Print(L);
break;
}
case 10:{
SeqList L;
InitSql(L);
Solution8(L);
Print(L);
break;
}
case 11:{
cout<<"此时序列的中位数是"<<Solution11()<<endl;
break;
}
case 12:{
SeqList L;
InitSql(L);
Solution12(L);
break;
}
case 13:{
SeqList L;
InitSql(L);
Solution13(L);
break;
}
default: break;
}
}
main(){
Menu();
}