顺序表的逆转

顺序表逆转是顺表基本操作之一,本将讨论顺序表逆转的基本方法,以及用顺序表逆转解决实际题目,本文将讨论三个问题

题目一

顺序表逆转
方法:直接循环将首尾元素交换。

void Reverse(Sqlist &L){
    int mid = (L.length-1)/2;
    for(int i=0; i<=mid; i++){
        int tmp = L.data[i];
        L.data[i] = L.data[L.length-1-i];
        L.data[L.length-1-i] = tmp;
    }
}

题目二

已知在一维数组A[m+n]中一次存放两个线性表 ( a 1 , a 2 , a 3 , &ThinSpace; , a m ) (a_1,a_2,a_3,\cdots,a_m) ( b 1 , b 2 , b 3 , &ThinSpace; , b n ) (b_1,b_2,b_3,\cdots,b_n) 。试编写一个函数,将数组中两个顺序表的位置互换,即将 ( b 1 , b 2 , b 3 , &ThinSpace; , b n ) (b_1,b_2,b_3,\cdots,b_n) 放在 ( a 1 , a 2 , a 3 , &ThinSpace; , a m ) (a_1,a_2,a_3,\cdots,a_m) 的前面。
思路:首先将数组A[m+n]中的全部元素 ( a 1 , a 2 , a 3 , &ThinSpace; , a m , b 1 , b 2 , b 3 , &ThinSpace; , b n ) (a_1,a_2,a_3,\cdots,a_m,b_1,b_2,b_3,\cdots,b_n) 原地逆置为 ( b n , b n 1 , b n 2 , &ThinSpace; , b 1 , a m , a m 1 , a m 2 , &ThinSpace; , m 1 ) (b_n,b_{n-1},b_{n-2},\cdots,b_1,a_m,a_{m-1},a_{m-2},\cdots,m_1) ,在对前n个元素和后m个元素分别使用逆置算法,即可得到 ( b 1 , b 2 , b 3 , &ThinSpace; , b n , a 1 , a 2 , a 3 , &ThinSpace; , a m ) (b_1,b_2,b_3,\cdots,b_n,a_1,a_2,a_3,\cdots,a_m) ,从而实现了顺序表的位置互换。

#include<iostream>
#include<stdio.h>
using namespace std;

struct Sqlist{
    int data[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    int length = 10;
};

void Reverse(Sqlist &L, int left, int right){
    int mid = (right-left)/2;
    for(int i=0; i<=mid; i++){
        int tmp = L.data[left-1+i];
        L.data[left-1+i] = L.data[right-1-i];
        L.data[right-1-i] = tmp;
    }
}

int main(){
    Sqlist L;
    for(int i=0; i<L.length; i++){
        printf("%d ", L.data[i]);
    }
    printf("\n");
    Reverse(L, 1, 10);
    Reverse(L, 1, 5);
    Reverse(L, 6, 10);
    for(int i=0; i<L.length; i++){
        printf("%d ", L.data[i]);
    }
}

题目三

试将 n ( n &gt; 1 ) n(n&gt;1) 个整数存放到一维数组R中,设计一个在时间和空间上都尽可能高效的算法。将R中保存的序列循环左移 p ( 0 &lt; p &lt; n ) p(0&lt;p&lt;n) 个位置,即将R中的数据由 ( x 0 , x 1 , &ThinSpace; , x n 1 ) (x_0,x_1,\cdots,x_{n-1}) 变换为 ( x p , x p + 1 , x n 1 , x 0 , x 1 , &ThinSpace; , x p 1 ) (x_p,x_{p+1},x_{n-1},x_0,x_1,\cdots,x_{p-1})
思路:这个题表面看起来是数组的循环左移,但仔细类比题目二,还是会发现由许多共通之处,同样可以可以看作把数组 a b ab 转换成 b a ba

#include<iostream>
#include<stdio.h>
using namespace std;

struct Sqlist{
    int data[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    int length = 10;
};

void Reverse(Sqlist &L, int left, int right){
    int mid = (right-left)/2;
    for(int i=0; i<=mid; i++){
        int tmp = L.data[left-1+i];
        L.data[left-1+i] = L.data[right-1-i];
        L.data[right-1-i] = tmp;
    }
}

int main(){
    Sqlist L;
    int n = 3; //循环左移3位
    for(int i=0; i<L.length; i++){
        printf("%d ", L.data[i]);
    }
    printf("\n");
    Reverse(L, 1, n);
    Reverse(L, n+1, 10);
    Reverse(L, 1, 10);
    for(int i=0; i<L.length; i++){
        printf("%d ", L.data[i]);
    }
}

  1. 三次逆转的时间复杂度分别为 O ( p / 2 ) , o ( ( n p ) / 2 ) O(p/2),o((n-p)/2) O ( n / 2 ) O(n/2) ,所以这个算法的时间复杂度为 O ( n ) O(n) ,空间复杂度为 O ( 1 ) O(1)
  2. 当然,循环移动数组还可以采用辅助数组实现,将R中前p个整数依次暂存在S中,
    再将R中后n-p个整数左移,最后将S中暂存的p个树一次放回到R中的后续单元。这样做损失了空间复杂度,不是最优的解法。
发布了37 篇原创文章 · 获赞 30 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_40941722/article/details/93870943
今日推荐