【数据结构】顺序表相关例题(部分)

1、逆置顺序表

题目:设计一个算法,将顺序表L中的一段连续元素逆置,要求算法的空间复杂度为O(1)。

思路:使用两个参数记录需要逆置的元素段的起始位置和末尾位置。设定一个辅助变量t,使用一个循环遍历该数组段的一半,将其与对称位置的元素调换,实现逆置。这里因为辅助变量只有一个,故满足空间复杂度要求。

void Reverse(int *T,int head,int tail){     //逆置函数
  int t;
  for(int i=0;i<((tail-head)/2);i++){
    t=T[i+head];
    T[i+head]=T[tail-i];
    T[tail-i]=t;
  }
}

2、循环移动顺序表元素

题目:设将n(n>1)个整数存放到一维数组R中。设计一个在时间和空间两方面都尽可能高效的算法。将R中保存的序列循环左移p(0<p<n)个位置,即将R中的数据由(X_{0},X_{1},...X_{n-1})变換为(X_{p},X_{p+1},...,X_{0},X_{1},...,X_{p-1})

解法1:创建一个长度为p的临时数组P,将原数组的前p位元素先存进P里,再将原数组的后n-p位元素向左移动p位,最后把P里的p个元素放回数组末尾。这样算法的时间复杂度为O(n),空间复杂度为O(p)。

代码如下:

#include <iostream>
using namespace std;

void Assign(int *R,int n) {             //赋值函数
    for(int i=0;i<n;i++)
        cin>>R[i];
}
void Movement(int *T,int n,int p){      //移动函数
    int *P=new int[p];                  //临时辅助数组
    int i;
    for(i=0;i<p;i++)                    //储存前p个
      P[i]=T[i];
    for(i=0;i<n-p;i++)                  //移动前n-p个
      T[i]=T[i+p];
    for(i=0;i<p;i++)                    //赋值后p个
      T[i+n-p]=P[i];
    delete[] P;
}

int main(){
    int n,p;
    cin>>n>>p;
    int *R=new int[n];
    Assign(R,n);                        //赋值
    Movement(R,n,p);                    //移动
    for(int i=0;i<n;i++)                //输出
      cout<<R[i];
    delete[] R;
    return 0;
}

解法2:给出一个示例ABCDEF,左移一位变成BCDEF A,移两位变为CDEF AB,移三位变为DEF ABC。观察可以得到,如果把数组的前p位假设为数组a,后n-p位假设为数组b,则移动p位等同于将ab变为ba。那么如何将ab变为ba呢?这里可以用到数组处理的一种常用方法,即将数组逆置。通过观察可以发现ba=((a)^{-1}(b)^{-1})^{-1},这里的()^{-1}为求逆操作,即将一维数组逆置。

这种方法看起来更复杂了一点,但是由于数组逆置算法的空间复杂度为O(1),事实上降低了空间复杂度。

代码如下:

#include <iostream>
using namespace std;

void Assign(int *R,int n) {                 //赋值函数
    for(int i=0;i<n;i++)
        cin>>R[i];
}

void Reverse(int *T,int head,int tail){     //逆置函数
  int t;
  for(int i=0;i<((tail-head)/2);i++){
    t=T[i+head];
    T[i+head]=T[tail-i];
    T[tail-i]=t;
  }
}

int main(){
  int n,p;
  cin>>n>>p;
  int *R=new int[n];
  Assign(R,n);                     //赋值函数
  Reverse(R,0,n-p-1);              //逆置前n-p个
  Reverse(R,n-p,n-1);              //逆置后p个
  Reverse(R,0,n-1);                //整体逆置
  for(int i=0;i<n;i++)
    cout<<R[i];
  delete[] R;
  return 0;
}

3、删除顺序表定值元素

题目:对长度为 n的顺序表L,编写一个时间复杂度为 O(n)、空间复杂度为 O(1)的算法,该算法删除顺序表中所有值为x的数据元素。

思路:在一次循环中遍历顺序表的所有元素,使用一个参数k记录至当前位置需要被删除的元素的个数,k初值为0。若遇到值为x的元素,则k加1,顺序表长度-1;若遇到非x的元素,将其前移k位。

代码如下:

#include <iostream>
using namespace std;

#define InitSize 50
typedef struct{                            //定义顺序表
    int *data;
    int MaxSize,length;
}Sqlist;

void InitSqlist(Sqlist &L){                //初始化
    L.MaxSize=InitSize;
    L.data=new int[L.MaxSize];
    L.length=0;
}

void Assign(Sqlist &L,int n) {             //赋值函数
    for(int i=0;i<n;i++){
        cin>>L.data[i];
        L.length++;
    }
}

void Delete(Sqlist &L,int x,int n){        //删除函数
    int k=0;                               //统计当前需删除的个数
    for(int i=0;i<n;i++) {
        if (L.data[i]==x) {
            k++;                           //当前需删除的个数+1,顺序表的长度-1
            L.length--;
        }
        else if (L.data[i]!=x)             //将不需要删除的元素前移k位
            L.data[i-k]=L.data[i];
    }
}

void Output(Sqlist L){                     //输出顺序表
  for(int i=0;i<L.length;i++)
    cout<<L.data[i]<<" ";
}

int main(){
    int n,x;
    cin>>n>>x;
    Sqlist R;                               //定义结构体
    InitSqlist(R);                          //初始化顺序表
    Assign(R,n);                            //顺序表赋值
    Delete(R,x,n);                          //调用删除函数
    Output(R);                              //调用输出函数
    return 0;
}

4、删除给定范围内顺序表元素

题目:从顺序表中删除其值在给定值s和t之间(包含s和t,要求s<t)的所有元素,若s或不合理或顺序表为空,则显示出错信息并退出运行。

思路:与上一题基本一致,加一个判定条件。

代码如下:
 

#include <iostream>
using namespace std;

#define InitSize 50
typedef struct{                            //定义顺序表
    int *data;
    int MaxSize,length;
}Sqlist;

void InitSqlist(Sqlist &L){                //初始化
    L.MaxSize=InitSize;
    L.data=new int[L.MaxSize];
    L.length=0;
}

void Assign(Sqlist &L,int n) {             //赋值函数
    for(int i=0;i<n;i++){
        cin>>L.data[i];
        L.length++;
    }
}

void Delete(Sqlist &L,int n,int s,int t){        //删除函数
    if(s>=t||L.length==0){
        cout<<"input false"<<endl;
        return;
    }
    int k=0;                               //统计当前需删除的个数
    for(int i=0;i<n;i++) {
        if (L.data[i]>=s&&L.data[i]<=t) {
            k++;                           //当前需删除的个数+1,顺序表的长度-1
            L.length--;
        }
        else                                //将不需要删除的元素前移k位
            L.data[i-k]=L.data[i];
    }
}

void Output(Sqlist L){                     //输出顺序表
    for(int i=0;i<L.length;i++)
        cout<<L.data[i]<<" ";
}

int main(){
    int n,s,t;
    cin>>n>>s>>t;
    Sqlist R;                               //定义结构体
    InitSqlist(R);                       //初始化顺序表
    Assign(R,n);                         //顺序表赋值
    Delete(R,n,s,t);                     //调用删除函数
    Output(R);                              //调用输出函数
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值