线性表顺序存储
一、顺序表定义
typedef struct {
int data[MaxSize];
int length;
}SqList;
二、顺序表题目及代码
1.从顺序表中删除具有最小值的元素(假设唯一)并由函数返回被删元素的值。空出的位置由最后一个元素填补,若顺序表为空,则显示出错信息并退出运行。
/*
* 算法思想:先判断表是否为空,如果为空返回false
* 如果不为空,用min存储表中最小的值,k用来存储最小值的下标
* 先令min等于表的第一个数即L.data[0]之后用min依次与表中的数进行比较,如果比min小,赋值给min,此时k++
* 最后把min赋值给e,将最后一个元素赋值给L.data[k]
*/
bool search_min(SqList &L,int &e){
if(L.length==0)
return false;
int min,k=0;
min=L.data[0];
for (int i = 1; i <L.length ; i++){
if(min>L.data[i]){
min=L.data[i];
k++;
}
}
e=min;
L.data[k]=L.data[L.length-1];
return true;
}
2.设计一个高效算法,将顺序表L的所有元素逆置,要求算法的空间复杂度为 O(1)。
/*
* 算法思想:先取mid为表中length/2,以mid为中心,第一个数和最后一个数进行逆置,第二个和倒数第二个进行逆置。。。
* 直到下标大于mid时逆置结束
*/
void Reverse(SqList &L){
int temp,mid=L.length/2;
for (int i = 0; i <=mid; ++i) {
temp=L.data[L.length-1-i];
L.data[L.length-1-i]=L.data[i];
L.data[i]=temp;
}
}
3.对长度为n 的顺序表 L,编写一个时间复杂度为 O(n)、空间复杂度为 O(1)的算法,该算法删除线性表中所有值为x的数据元素。
/*
* 算法思想:当L.data[i]=x时,k不变,i++;(相当于有两个数组),若不等于x时,k和i都向后查询
*/
void Delete_x(SqList &L,int x){
int k=0;
for (int i = 0; i < L.length; ++i) {
if(L.data[i]!=x)
L.data[k++]=L.data[i];
}
L.length=k;
}
4.从有序顺序表中删除其值在给定值 s与 t之间(要求 s<t)的所有元素,若 s 或t不合理或顺序表为空,则显示出错信息并退出运行。
/*
* 算法思想:在3的基础上加一个判断条件:要删除的值是否在s和t之间
* 若在s,t之间,则不进行赋值,不在s和t之间不进行赋值
*/
void Delete_st(SqList &L,int left,int right){
if(left>right || L.length==0){
printf("false");
return;
}
int k=0;
for (int i = 0; i < L.length; ++i) {
if(L.data[i]<=left || L.data[i]>=right)
{
L.data[k++]=L.data[i];
}
}
L.length =k;
}
5.从有序顺序表中删除所有其值重复的元素,使表中所有元素的值均不同。
/ * 算法思想:新增一个空数组,顺序表中的每个数与新数组的最后一个数作比较,若不相等赋值到新的空数组中,直到遍历到最后一个数
* 再把新的数组的值复制到顺序表中
*/
void Delete_Re(SqList &L){
int b[MaxSize];
int k=0;
b[0]=L.data[0];
for (int i = 1; i < L.length; ++i) {
if(b[k]!=L.data[i]){
b[++k]=L.data[i];
}
}
for (int j = 0; j <=k; ++j) {
L.data[j]=b[j];
}
L.length=k+1;
}
6.将两个有序顺序表合并为一个新的有序顺序表,并由函数返回结果顺序表。
/*
* 算法思想:新建一个顺序表
* 将L和I的数进行比较,当L的数大于I的数,将I的数赋值给新的顺序表,I继续向后遍历;
* 若L的数小于I的数,将L的数赋值给新的顺序表,L继续向后遍历;
* 当L或者I任意一个遍历完后,将没有遍历的数向后赋值到新顺序表中
*/
SqList merge0(SqList M,SqList N){
SqList a;
int i=0,j=0,k=0;
while (i<M.length && j<N.length){
if (M.data[i]>=N.data[j]){
a.data[k++]=N.data[j++];
} else{
a.data[k++]=M.data[i++];
}
}
while (i<M.length){
a.data[k++]=M.data[i++];
}
while (j<N.length){
a.data[k++]=N.data[j++];
}
a.length=k;
return a;
}
7.已知在一维数组 A[m + n]中依次存放两个线性表(a1,a2, …,am)和(b1, b2, b3,…, bn)。编写一个函数,将数组中两个顺序表的位置互换,即将(b1, b2, b3,…, bn)放在(a1,a2, …,am)的前面。
/*
* 算法思想:先把前m个逆置,再把后n个逆置,最后把整体逆置
*/
void reverse1(SqList &L,int left,int right){
int mid=(left+right)/2+1;
int temp;
for (int i = left; i < mid; ++i) {
temp=L.data[right+left-i];
L.data[right+left-i]=L.data[i];
L.data[i]=temp;
}
}
void reverse2(SqList &L,int m,int n){
reverse1(L,0,m-1);
reverse1(L,m,m+n-1);
reverse1(L,0,m+n-1);
}
8.线性表(a1,a2, a3,…,an)中的元素递增有序且按顺序存储于计算机内。要求设计一个算法,完成用最少时间在表中查找数值为x的元素,若找到,则将其与后继元素位置相交换,若找不到,则将其插入表中并使表中元素仍递增有序。
/*
* 算法思想:二分查找法
* 用mid定义为中间的数,如果x=mid,则进行交换
* 如果不相等,进行x与mid大小的判断,x大在mid后方找,此时low=mid+1,high不变,再次算出low到high的中间值,再与mid进行比较
* x小在mid前方找,此时low不变,high=mid-1,再次算出low到high的中间值,再与mid进行比较
* 若找出,直接跳出循环,与后面的值进行交换
* 当low大于high时,说明顺序表内不存在x,此时进行插入
*/
void findx(SqList &L,int x){
int low=0,high=L.length-1,mid;
while (low<high){
mid=(low+high)/2;
if(L.data[mid]==x){
int temp;
temp=L.data[mid+1];
L.data[mid+1]=L.data[mid];
L.data[mid]=temp;
break;
}else if(L.data[mid]>x){
high=mid-1;
} else{
low=mid+1;
}
}
if (low>=high){
L.length++;
int i;
for ( i = L.length; i >low; --i) {
L.data[i]=L.data[i-1];
}
L.data[low]=x;
}
}
9.一个长度为 L(L≥ 1)的升序序列 S,处在第[L/2]个位置的数称为 S的中位数。例如,若序列 S1=(11,13,15,17,19)。则S的中位数是 15,两个序列的中位数是含它们所有元素的升度序列的中位数。例如,若S2=(2,4,6,8,20),则 S1和S2的中位数是11。现在有两个等长升序序列A和B,试设计一个在时间和空间两方面都尽可能高效的算法,找出两个序列 A和B的中位数。【2011统考真题】
/*
* 算法思想:在归并方法上进行改进(不再新建一个数组):S1和S2依次向后遍历,k记录下标
* 当k=S1的长度时,停止查找,k就是中位数的下标
*/
int find_mid(SqList M,SqList N){
int i=0,j=0,k=0,value;
while (k!=M.length){
k++;
if(M.data[i]<N.data[j]){
value=M.data[i];
i++;
} else{
value=N.data[j];
j++;
}
}
return value;
}
11.已知一个整数序列A=(a1,a2,…,an-1),其中 0≤ai<n (0≤i<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。【2013统考真题】
/*
* 由题知,A数组里面的数是在0~n-1,那么可以新建一个长度为n的空数组count,其下标恰好也是0~n-1
* 可以用count的下标来表示A数组里面每一个数,每传来A的一个数,在count对应下标的数值++,即记录A中每个数出现的次数
* 对A遍历完成后,对count进行遍历,找里面>n/2的下标
*/
int find_main(SqList L){
int i;
int *count=(int *) malloc(sizeof (int)*L.length);
for (i=0; i < L.length; ++i) {
count[i]=0;
}
for (int i= 0; i< L.length; ++i) {
count[L.data[i]]++;
}
for (i = 0; i < L.length; ++i) {
if(count[i]>L.length/2){
break;
}
}
if(i==L.length){
return -1;
} else return i;
}
12.给定一个含n(n≥1)个整数的数组,请设计一个在时间上尽可能高效的算法,找出数组中未出现的最小正整数。例如,数组{-5,3,2,3}中未出现的最小正整数是1;数组{1,2,3}中未出现的最小正整数是4。【2018统考真题】
/*
* 算法思想:
* 新建一个空数组count,长度为L中最大的数值+2
* 之后对原数组中大于等于0的数去找count中相应下标,其数值自增1,最后对数组count遍历,找出第一个值为0跳出循环
* 此时的下标就是未出现的最小正整数
*/
int find_int(SqList L){
int max=L.data[0];
for (int i = 0; i < L.length; ++i) {
if (max < L.data[i]) {
max=L.data[i];
}
}
printf("max is %d\n",max);
int *count=(int *) malloc(sizeof (int)*(max+2));
for (int i = 0; i < max+2; ++i) {
count[i]=0;
}
for (int i = 0; i < max+2; ++i) {
if(L.data[i]>0){
count[L.data[i]]=1;
}
}
int i;
for (i=1; i < max+2; ++i) {
if (count[i]==0){
return i;
}
}
return 0;
}
13.定义三元组(a,b,c)(a、b、c均为正数)的距离D=|a-b|+|b-c|+|c-a|。给定3个非空整数集合S1、S2和S3按升序分别存储在3个数组中。请设计一个尽可能高效的算法,计算并输出所有可能的三元组(a,b,c)(aES1,bES2,cES3)中的最小距离。例如S={-1,0,9},S2{-25,-10,10,11},S={2,9,17,30,41},则最小距离为2,相应的三元组为(9,10,9)。【2020统考真题】
/*
* 算法思想:写三层嵌套循环
*/
int abs(int a){
if(a<0){
a=-a;
}
return a;
}
int distance_min(SqList L,SqList J,SqList I){
int a=0,b=0,c=0;
for (int i = 0; i < L.length; ++i) {
if (L.data[i] > 0) {
a++;
}
}
for (int j = 0; j <J.length ; ++j) {
if(J.data[j]>0){
b++;
}
}
for (int f = 0; f <I.length ; ++f) {
if(I.data[f]>0){
c++;
}
}
int d=a*b*c;
SqList ax;
int p=0;
ax.length=d;
for (int i = 0; i < ax.length; ++i) {
ax.data[i]=0;
}
for (int i = 0; i < L.length; ++i) {
if(L.data[i]>0){
for (int j = 0; j < J.length; ++j) {
if (J.data[j]>0){
for (int k = 0; k < I.length; ++k) {
ax.data[p++]= abs(L.data[i]-J.data[j])+ abs(L.data[i]-I.data[k])+ abs(J.data[j]-I.data[k]);
}
}
}
}
}
int min=ax.data[0];
for (int i = 0; i < ax.length; ++i) {
if(min>ax.data[i]){
min=ax.data[i];
}
}
return min;
}
三、递归
1、递归逆向输出顺序表
void f2(SqList L,int n){
if (n<L.length-1){
f2(L,n+1);
}
printf("%d",L.data[n]);
return;
}
2、递归正向输出顺序表
int f3(SqList L,int n){
if (n==L.length){
return -1;
}
printf("%d",L.data[n]);
return f3(L,n=n+1);
}
3、递归二分查找法
int DG_two(SqList L,int x,int low,int high){
int mid=(low+high)/2;
if (L.data[mid]==x || low>high){
return mid;
}
if (x<L.data[mid]){
high=mid;
} else low=mid;
return DG_two(L,x,low,high);
}
总结
以上就是今天的所有内容