1、从顺序表中删除具有最小值的元素,返回被删除的元素的值。
#include <iostream>
#include <string>
#include <cmath>
using namespace std;
typedef int ElemType;
int A[5];
#define inital 100
typedef struct{
int *data;
int MaxSize,length;
}SeqList;
bool DeleteMin(SeqList &L)//第一题
{
int minn=INT_MAX;
int i=0;
if(L.length==0) return false;
for(int j=0;j<L.length;j++)
{
if(L.data[j]<=minn)
{ minn=L.data[j];i=j;}
}
L.data[i]=L.data[L.length-1];
L.data[L.length-1]=NULL;
L.length--;
return minn;
}
算法:1.遍历找最值,确定位序。
2.最后一个元素填补
2、逆置L的所有元素,空间复杂度O(1)
void invert(SeqList &L)//第二题
{
ElemType *a;
a=new ElemType[inital];
for(int i=0;i<L.length;i++)
a[i]=L.data[i];
for(int i=0;i<L.length;i++)
L.data[i]=a[L.length-1-i];
}
空间逆置可以借助一个数组来实现,答案的方法是将
L.data[i]与L.data[L.length-i-1]交换
答案的方法更简单。
3、对长度n的顺序表L,写时间复杂度O(n),空间复杂度O(1)的算法,删除线性表中所有值为x的元素。
void Deletex(SeqList &L,ElemType x)//第三题
{
int k=1;
for(int i=0;i<L.length;i++)
{
int b=0;
if(L.data[i-1]==x&&L.data[i]!=x)
{b=L.data[i-k];L.data[i-k]=L.data[i];L.data[i]=b;}
if(L.data[i-1]==x&&L.data[i]==x) k++;
}
L.length=L.length-k;
}
设置k来记录连续出现的x的个数,通过交换数值的方法然后把所有的x挤到尾端,直接截掉。
4、从有序顺序表中删除s到t之间的元素,如果s、t不合理或者为空,显示错误结束运行。
bool Deletest1(SeqList &L,ElemType s,ElemType t)//第四题
{
if(s>t||s==t||L.length==0) return false;
int k=1;
for(int i=0;i<L.length;i++)
{
int a,b,c=0;
if(L.data[i-1]>s&&L.data[i-1]<t) a=1;
else a=0;
if(L.data[i]>s&&L.data[i]<t) b=1;
else b=0;
if(a&&!b)
{c=L.data[i-k];L.data[i-k]=L.data[i];L.data[i]=c;}
if(a&&b) k++;
}
L.length=L.length-k;
return true;
}
这个算法麻烦了,借助顺序表的特点,我们可以确定起始端和结束端,然后将这一部分挤到最后的位置,然后截掉这一部分。
5、从顺序表(非有序)中删除s到t的元素
bool Deletest2(SeqList &L,ElemType s,ElemType t)//第五题
{
if(s>t||s==t||L.length==0) return false;
int k=1;
for(int i=0;i<L.length;i++)
{
int a,b,c=0;
if(L.data[i-1]>=s&&L.data[i-1]<=t) a=1;
else a=0;
if(L.data[i]>=s&&L.data[i]<=t) b=1;
else b=0;
if(a&&!b)
{c=L.data[i-k];L.data[i-k]=L.data[i];L.data[i]=c;}
if(a&&b) k++;
}
L.length=L.length-k;
return true;
}
和删除x元素同理,区别就是x变成多值了。
6、删除顺序表中的重复元素
void DeleteSame(SeqList &L)//第六题
{
int *L1;
L1=new ElemType[inital];
delete L1;
memset(L1,0,inital*sizeof(int));
int max=INT_MIN;
for(int i=0;i<L.length;i++)
{
L1[L.data[i]]++;
if(L.data[i]>max) max=L.data[i];
}
for(int i=0;i<=max;i++)
{
int x=0;int k=0;int first=1;
if(L1[i]>1)
{ x=i;
for(int i=0;i<L.length;i++)
{
int b=0;
if(L.data[i-1]==x) first=0;
if(L.data[i-1]==x&&L.data[i]!=x&&first)
{b=L.data[i-k];L.data[i-k]=L.data[i];L.data[i]=b;}
if(L.data[i-1]==x&&L.data[i]==x&&first) k++;
}
L.length=L.length-k;
}
}
}
这里借助了一个辅助数组进行计数,确定了每个元素的重复次数,元素做下标,对应下标的数值不断加一就行,最后遍历数组找到那些大于一的部分,这些部分的下标就是要删除的元素。设置first变量防止第一个出现的元素被删除。
7、合并两个有序顺序表为一个有序顺序表
循环,两两比较,找到小的放到新表中,多的放到后面,这里要注意确定多的是哪个表。
8、互换顺序表的位置
ElemType *change(ElemType *A,int m,int n)//第八题
{
ElemType *B;
B=new ElemType[inital];
int j=0;
for(int i=m;i<m+n-1;i++)
{B[j]=A[i];j++;}
for(int i=0;i<m;i++)
{B[j]=A[i];j++;}
return B;
}
借助辅助表,直接出答案,这是很蠢的方法。
9、在递增顺序表中找出x,与后继元素进行交换
void search(SeqList &L,int x)//第九题
{
int a,b,c=0;
for(int i=0;i<L.length;i++)
{
if(L.data[i]==x&&i!=L.length-1)
{
b=L.data[i];
L.data[i]=L.data[i+1];
L.data[i+1]=b;
a=1;
}
if(L.data[i-1]<x&&L.data[i]>x) {c=i;break;}
if(L.data[0]>x) {c=i;break;}
if(L.data[L.length-1]<x) {c=i;break;}
}
c=c+1;
if(!a)
{
for(int i=L.length;i>=c;i--) L.data[i]=L.data[i-1];
L.data[c-1]=x;
L.length++;
}
}
这里是个重点,最简单的方法当然是二分查找,可以用递归实现,也可以简化为折半查找,直接做一步就行了。
12、找主元素,比如A=(0,5,5,3,5,7,5,5)的5是主元素,A=(0,5,5,3,5,1,5,7)没有主元素,主元素需要重复出现最多而且个数大于n/2。
int tk3(int *A,int n)//第十二题
{
int *B;
B=new int[inital];
memset(B,0,inital*sizeof(int));
int max=INT_MIN;
for(int i=0;i<n;i++)
{
B[A[i]]++;
if(A[i]>=max) max=A[i];
}
for(int i=0;i<=max;i++)
if(B[i]>floor(n/2)) return i;
return -1;
}
借助辅助数组,找到重复次数最多的元素,最后判断元素是否满足条件,注意用floor取整不是ceil取整。
这里还要注意一个地方,分配动态内存的指针的初始化用语句:
B=new int[inital];
memset(B,0,inital*sizeof(int));
13、找数组中未出现的最小正整数,比如{-5,3,2,3}中是1,{1,2,3}中是4
int tk4(int *A,int n)//第十三题
{
int j=1;
for(j=1;;)
{
int p=0;
for(int i=0;i<n;i++)
{
if(A[i]>0&&A[i]==j) p++;
if(p) break;
}
if(!p) return j;
j++;
}
return 0;
}
这个很简单,从1开始遍历,发现数组中有这个就比较下一个,如果没发现直接输出这个整数就行了。这个复杂度可能有点高,但是想法还不错。