顺序表习题选做

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开始遍历,发现数组中有这个就比较下一个,如果没发现直接输出这个整数就行了。这个复杂度可能有点高,但是想法还不错。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值