SDUT专题整理——顺序表

顺序表应用1:多余元素删除之移位算法
Time Limit: 1000MS Memory Limit: 650KB

Problem Description
一个长度不超过10000数据的顺序表,可能存在着一些值相同的“多余”数据元素(类型为整型),编写一个程序将“多余”的数据元素从顺序表中删除,使该表由一个“非纯表”(值相同的元素在表中可能有多个)变成一个“纯表”(值相同的元素在表中只保留第一个)。
要求:
1、必须先定义线性表的结构与操作函数,在主函数中借助该定义与操作函数调用实现问题功能;
2、本题的目标是熟悉顺序表的移位算法,因此题目必须要用元素的移位实现删除;

Input
第一行输入整数n,代表下面有n行输入;
之后输入n行,每行先输入整数m,之后输入m个数据,代表对应顺序表的每个元素。

Output
输出有n行,为每个顺序表删除多余元素后的结果

Example Input
4
5 6 9 6 8 9
3 5 5 5
5 9 8 7 6 5
10 1 2 3 4 5 5 4 2 1 3

Example Output
6 9 8
5
9 8 7 6 5
1 2 3 4 5

Hint

Author

以下为Accepted代码1——结构体

#include 

using namespace std;

struct Table{
    int size;
    int *num;
};

void Build(Table &a, int n);/*建表*/
void move_num(Table &a);/*移位算法删除重复元素*/
void pri_num(Table &a);/*输出删除重复元素之后的序列*/

int main(){
    int T, n;
    Table a;/*定义表a*/
    cin >> T;
    while(T--){
        cin >> n;
        Build(a, n);
        move_num(a);
        pri_num(a);
    }
    return 0;
}
void Build(Table &a, int n){
    a.size = n;
    a.num = new int[11400];
    for(int i = 0; i < n; i++)
        cin >> a.num[i];
}
void move_num(Table &a){
    for(int i = 0; i < a.size; i++){
        int j = i + 1;
        while(j < a.size){
            if(a.num[i] != a.num[j])
                j++;
            else {
                for(int k = j; k < a.size-1; k++)
                    a.num[k] = a.num[k+1];
                a.size--;
            }
        }
    }
}
void pri_num(Table &a){
    for(int i = 0; i < a.size; i++){
        cout << a.num[i];
        i == a.size-1? cout << '\n': cout << ' ';
    }
    delete []a.num;
}


/*************************************************** User name: Result: Accepted Take time: 44ms Take Memory: 244KB Submit time: 2017-09-15 16:53:15 ****************************************************/

以下为Accepted代码2——C++类

#include 

using namespace std;

class Table{
private:
    int size;
    int *num;
public:
    void build_table(int n);
    void move_num();
    void pri_num();
    void delete_memory();
};

void Table::build_table(int n){
    size = n;
    num = new int[n+4];
    for(int i = 0; i < n; i++)
        cin >> num[i];
}
void Table::move_num(){
    for(int i = 0; i < size; i++){
        int j = i + 1;
        while(j < size){
            if(num[i] != num[j])
                j++;
            else {
                for(int k = j; k < size-1; k++)
                    num[k] = num[k+1];
                size--;
            }
        }
    }
}
void Table::pri_num(){
    for(int i = 0; i < size; i++){
        cout << num[i];
        i == size-1? cout << '\n': cout << ' ';
    }
}
void Table::delete_memory(){
    delete []num;
}

int main(){
    int T, n;
    Table test;
    cin >> T;
    while(T--){
        cin >> n;
        test.build_table(n);
        test.move_num();
        test.pri_num();
        test.delete_memory();
    }
    return 0;
}


/*************************************************** User name: Result: Accepted Take time: 44ms Take Memory: 244KB Submit time: 2017-09-15 17:06:33 ****************************************************/

顺序表应用2:多余元素删除之建表算法
Time Limit: 3MS Memory Limit: 600KB

Problem Description
一个长度不超过10000数据的顺序表,可能存在着一些值相同的“多余”数据元素(类型为整型),编写一个程序将“多余”的数据元素从顺序表中删除,使该表由一个“非纯表”(值相同的元素在表中可能有多个)变成一个“纯表”(值相同的元素在表中只保留第一个)。
要求:
1、必须先定义线性表的结构与操作函数,在主函数中借助该定义与操作函数调用实现问题功能;
2、本题的目标是熟悉在顺序表原表空间基础上建新表的算法,要在原顺序表空间的基础上完成完成删除,建表过程不得开辟新的表空间;
3、不得采用原表元素移位删除的方式。

Input
第一行输入整数n,代表下面有n行输入;
之后输入n行,每行先输入整数m,之后输入m个数据,代表对应顺序表的每个元素。

Output
输出有n行,为每个顺序表删除多余元素后的结果

Example Input
4
5 6 9 6 8 9
3 5 5 5
5 9 8 7 6 5
10 1 2 3 4 5 5 4 2 1 3

Example Output
6 9 8
5
9 8 7 6 5
1 2 3 4 5

Hint

Author

以下为Accepted代码

#include 

using namespace std;

struct Table{
    int size;
    int *num;
};

void build_table(Table &a, int n);/*建表*/
void rebuild_table(Table &a);/*通过表的重建删除重复元素*/
void pri_table(Table &a);/*输出新表(去除重复元素之后的序列)*/
void delete_memory(Table &a);/*释放内存*/

int main(){
    int T, n;
    Table a;
    cin >> T;
    while(T--){
        cin >> n;
        build_table(a, n);
        rebuild_table(a);
        pri_table(a);
        delete_memory(a);
    }
    return 0;
}
void build_table(Table &a, int n){
    a.size = n;
    a.num = new int[n+4];
    for(int i = 0; i < n; i++)
        cin >> a.num[i];
}
void rebuild_table(Table &a){
    int i, j, k = 0;
    for(i = 0; i < a.size; i++){
        for(j = 0; j < k; j++){
            if(a.num[j] == a.num[i])
                break;
        }
        if(k == 0 || j == k)
            a.num[k++] = a.num[i];
    }
    a.size = k;
}
void pri_table(Table &a){
    for(int i = 0; i < a.size; i++){
        cout << a.num[i];
        i == a.size-1? cout << '\n': cout << ' ';
    }
}
void delete_memory(Table &a){
    delete []a.num;
}


/*************************************************** User name: Result: Accepted Take time: 4ms Take Memory: 264KB Submit time: 2017-09-15 17:29:35 ****************************************************/

顺序表应用3:元素位置互换之移位算法
Time Limit: 1000MS Memory Limit: 570KB

Problem Description
一个长度为len(1<=len<=1000000)的顺序表,数据元素的类型为整型,将该表分成两半,前一半有m个元素,后一半有len-m个元素(1<=m<=len),借助元素移位的方式,设计一个空间复杂度为O(1)的算法,改变原来的顺序表,把顺序表中原来在前的m个元素放到表的后段,后len-m个元素放到表的前段。
注意:先将顺序表元素调整为符合要求的内容后,再做输出,输出过程只能用一个循环语句实现,不能分成两个部分。

Input
第一行输入整数n,代表下面有n行输入;
之后输入n行,每行先输入整数len与整数m(分别代表本表的元素总数与前半表的元素个数),之后输入len个整数,代表对应顺序表的每个元素。

Output
输出有n行,为每个顺序表前m个元素与后(len-m)个元素交换后的结果

Example Input
2
10 3 1 2 3 4 5 6 7 8 9 10
5 3 10 30 20 50 80

Example Output
4 5 6 7 8 9 10 1 2 3
50 80 10 30 20

Hint
注意:先将顺序表元素调整为符合要求的内容后,再做输出,输出过程只能在一次循环中完成,不能分成两个部分输出。

Author

以下为Accepted代码

#include 

using namespace std;

struct Table{
    int len, m;
    int *num;
};

void build_table(Table &a, int len, int m);/*建表*/
void rebuild_table(Table &a);/*调整序列*/
void swap_num(Table &a, int l, int r);/*交换数组a.num中区间[l, r]的数*/
void pri_num(Table &a);/*输出序列中的数*/
void delete_memory(Table &a);/*释放内存*/

int main(){
    int T, len, m;
    Table test;
    cin >> T;
    while(T--){
        cin >> len >> m;
        build_table(test, len, m);
        rebuild_table(test);
        pri_num(test);
        delete_memory(test);
    }
    return 0;
}
void build_table(Table &a, int len, int m){
    a.len = len, a.m = m;
    a.num = new int[len+4];
    for(int i = 1; i <= len; i++)
        cin >> a.num[i];
}
void rebuild_table(Table &a){
    swap_num(a, 1, a.m);
    swap_num(a, a.m+1, a.len);
    swap_num(a, 1, a.len);
}
void swap_num(Table &a, int l, int r){
    int t, mid = (l+r)/2;
    for(int i = l; i <= mid; i++){
        t = a.num[i], a.num[i] = a.num[l+r-i], a.num[l+r-i] = t;
    }
}
void pri_num(Table &a){
    for(int i = 1; i <= a.len; i++){
        cout << a.num[i];
        i == a.len? cout << '\n': cout << ' ';
    }
}
void delete_memory(Table &a){
    delete []a.num;
}


/*************************************************** User name: Result: Accepted Take time: 8ms Take Memory: 244KB Submit time: 2017-09-15 17:51:39 ****************************************************/

顺序表应用4-2:元素位置互换之逆置算法(数据改进)
Time Limit: 80MS Memory Limit: 600KB

Problem Description
一个长度为len(1<=len<=1000000)的顺序表,数据元素的类型为整型,将该表分成两半,前一半有m个元素,后一半有len-m个元素(1<=m<=len),设计一个时间复杂度为O(N)、空间复杂度为O(1)的算法,改变原来的顺序表,把顺序表中原来在前的m个元素放到表的后段,后len-m个元素放到表的前段。
注意:交换操作会有多次,每次交换都是在上次交换完成后的顺序表中进行。

Input
第一行输入整数len(1<=len<=1000000),表示顺序表元素的总数;
第二行输入len个整数,作为表里依次存放的数据元素;
第三行输入整数t(1<=t<=30),表示之后要完成t次交换,每次均是在上次交换完成后的顺序表基础上实现新的交换;
之后t行,每行输入一个整数m(1<=m<=len),代表本次交换要以上次交换完成后的顺序表为基础,实现前m个元素与后len-m个元素的交换;

Output
输出一共t行,每行依次输出本次交换完成后顺序表里所有元素。

Example Input
10
1 2 3 4 5 6 7 8 9 -1
3
2
3
5

Example Output
3 4 5 6 7 8 9 -1 1 2
6 7 8 9 -1 1 2 3 4 5
1 2 3 4 5 6 7 8 9 -1

Hint

Author

以下为Accepted代码

#include 
#include 
#include 

using namespace std;

struct Table{
    int len;
    int *num;
};

void build_table(Table &a, int len);/*建表*/
void rebuild_table(Table &a, int m);/*移位互换*/
void swap_num(Table &a, int l, int r);/*将数组a.num在区间[l, r]的数转置*/
void pri_num(Table &a);/*输出当前状态的序列*/
void delete_memory(Table &a);/*释放内存*/

int main(){
    int len, T, m;
    Table test;
    while(~scanf("%d", &len)){
        build_table(test, len);
        scanf("%d", &T);
        while(T--){
            scanf("%d", &m);
            rebuild_table(test, m);
            pri_num(test);
        }
        delete_memory(test);
    }
    return 0;
}
void build_table(Table &a, int len){
    a.len = len;
    a.num = new int[len+4];
    for(int i = 1; i <= len; i++)
        scanf("%d", &a.num[i]);
}
void rebuild_table(Table &a, int m){
    swap_num(a, 1, m);
    swap_num(a, m+1, a.len);
    swap_num(a, 1, a.len);
}
void swap_num(Table &a, int l, int r){
    int t, mid = (l+r)/2;
    for(int i = l; i <= mid; i++){
        t = a.num[i], a.num[i] = a.num[r+l-i], a.num[r+l-i] = t;
    }
}
void pri_num(Table &a){
    for(int i = 1; i <= a.len; i++){
        printf("%d%c", a.num[i], i == a.len? '\n': ' ');
    }
}
void delete_memory(Table &a){
    delete []a.num;
}


/*************************************************** User name: Result: Accepted Take time: 80ms Take Memory: 556KB Submit time: 2017-09-15 21:53:37 ****************************************************/

顺序表应用5:有序顺序表归并
Time Limit: 100MS Memory Limit: 880KB

Problem Description
已知顺序表A与B是两个有序的顺序表,其中存放的数据元素皆为普通整型,将A与B表归并为C表,要求C表包含了A、B表里所有元素,并且C表仍然保持有序。

Input
输入分为三行:
第一行输入m、n(1<=m,n<=10000)的值,即为表A、B的元素个数;
第二行输入m个有序的整数,即为表A的每一个元素;
第三行输入n个有序的整数,即为表B的每一个元素;

Output
输出为一行,即将表A、B合并为表C后,依次输出表C所存放的元素。

Example Input
5 3
1 3 5 6 9
2 4 10

Example Output
1 2 3 4 5 6 9 10

Hint

Author

以下为Accepted代码

#include 

using namespace std;

struct Table{
    int size;
    int *num;
};

void build_table(Table &a, int len);
Table union_table(Table &a, Table &b);
void pri_table(Table &a);
void delete_table(Table &a);

int main(){
    int m, n;
    Table a, b, c;
    while(cin >> m >> n){
        build_table(a, m);
        build_table(b, n);
        c = union_table(a, b);
        pri_table(c);
        delete_table(a);
        delete_table(b);
        delete_table(c);
    }
    return 0;
}
void build_table(Table &a, int len){
    a.size = len;
    a.num = new int[len+4];
    for(int i = 0; i < len; i++)
        cin >> a.num[i];
}
Table union_table(Table &a, Table &b){
    Table c;
    c.size = a.size + b.size;
    c.num = new int[c.size+4];
    int i = 0, j = 0, k = 0;
    while(i < a.size && j < b.size){
        if(a.num[i] < b.num[j]){
            c.num[k++] = a.num[i];
            i++;
        }
        else {
            c.num[k++] = b.num[j];
            j++;
        }
    }
    while(i < a.size){
        c.num[k++] = a.num[i];
        i++;
    }
    while(j < b.size){
        c.num[k++] = b.num[j];
        j++;
    }
    return c;
}
void pri_table(Table &a){
    for(int i = 0; i < a.size; i++){
        cout << a.num[i];
        i == a.size-1? cout << '\n': cout << ' ';
    }
}
void delete_table(Table &a){
    delete []a.num;
}


/*************************************************** User name: Result: Accepted Take time: 16ms Take Memory: 356KB Submit time: 2017-09-15 22:04:04 ****************************************************/

顺序表应用6:有序顺序表查询
Time Limit: 1000MS Memory Limit: 4096KB

Problem Description
顺序表内按照由小到大的次序存放着n个互不相同的整数,任意输入一个整数,判断该整数在顺序表中是否存在。如果在顺序表中存在该整数,输出其在表中的序号;否则输出“No Found!”。

Input
第一行输入整数n (1 <= n <= 100000),表示顺序表的元素个数;
第二行依次输入n个各不相同的有序非负整数,代表表里的元素;
第三行输入整数t (1 <= t <= 100000),代表要查询的次数;
第四行依次输入t个非负整数,代表每次要查询的数值。
保证所有输入的数都在 int 范围内。

Output
输出t行,代表t次查询的结果,如果找到在本行输出该元素在表中的位置,否则本行输出No Found!

Example Input
10
1 22 33 55 63 70 74 79 80 87
4
55 10 2 87

Example Output
4
No Found!
No Found!
10

Hint

Author

#include 
#include 
#include 

using namespace std;

struct Table{
    int size;
    int *num;
};

void build_table(Table &L, int n);/*建表*/
void search_x(Table L, int x);/*二分查找*/
void delete_table(Table &L);/*释放内存*/

int main(){
    int n, q, x;
    Table test;
    while(~scanf("%d", &n)){
        build_table(test, n);
        scanf("%d", &q);
        while(q--){
            scanf("%d", &x);
            search_x(test, x);
        }
        delete_table(test);
    }
    return 0;
}
void build_table(Table &L, int n){
    L.size = n;
    L.num = new int[n+4];
    for(int i = 1; i <= n; i++)
        scanf("%d", &L.num[i]);
}
void search_x(Table L, int x){
    int l, r, mid;
    l = 1, r = L.size;
    while(l <= r){
        mid = (l+r)>>1;
        if(L.num[mid] == x){
            printf("%d\n", mid);
            return;
        }
        else if(L.num[mid] > x){
            r = mid-1;
        }
        else if(L.num[mid] < x){
            l = mid + 1;
        }
    }
    printf("No Found!\n");
    return;
}
void delete_table(Table &L){
    delete []L.num;
}


/*************************************************** User name: Result: Accepted Take time: 60ms Take Memory: 508KB Submit time: 2017-09-20 20:47:20 ****************************************************/

顺序表应用7:最大子段和之分治递归法
Time Limit: 10MS Memory Limit: 400KB

Problem Description
给定n(1<=n<=50000)个整数(可能为负数)组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。当所给的整数均为负数时定义子段和为0,依此定义,所求的最优值为: Max{0,a[i]+a[i+1]+…+a[j]},1<=i<=j<=n。 例如,当(a[1],a[2],a[3],a[4],a[5],a[6])=(-2,11,-4,13,-5,-2)时,最大子段和为20。
注意:本题目要求用分治递归法求解,除了需要输出最大子段和的值之外,还需要输出求得该结果所需的递归调用总次数。
递归调用总次数的获得,可以参考以下求菲波那切数列的代码段中全局变量count的用法:

#include
int count=0;
int main()
{
    int n,m;
    int fib(int n);
    scanf("%d",&n);
    m=fib(n);
    printf("%d %d\n",m,count);
    return 0;
}
int fib(int n)
{
    int s;
    count++;
    if((n==1)||(n==0)) return 1;
    else s=fib(n-1)+fib(n-2);
    return s;
}

Input
第一行输入整数n(1<=n<=50000),表示整数序列中的数据元素个数;
第二行依次输入n个整数,对应顺序表中存放的每个数据元素值。

Output
一行输出两个整数,之间以空格间隔输出:
第一个整数为所求的最大子段和;
第二个整数为用分治递归法求解最大子段和时,递归函数被调用的总次数。

Example Input
6
-2 11 -4 13 -5 -2

Example Output
20 11

Hint

Author

以下为Accepted代码

#include 
#include 
#include 

using namespace std;

struct Table{
    int size;
    int *num;
};

int cnt;

void build_table(Table &L, int n);/*建表*/
int max_sum(Table L, int l, int r);/*分治递归法求解最大子段和*/
void delete_table(Table &L);/*释放内存*/

int main(){
    int n, ans;
    Table test;
    while(~scanf("%d", &n)){
        cnt = 0;
        build_table(test, n);
        ans = max_sum(test, 1, n);
        printf("%d %d\n", ans, cnt);
        delete_table(test);
    }
    return 0;
}
void build_table(Table &L, int n){
    L.size = n;
    L.num = new int[n+4];
    for(int i = 1; i <= n; i++){
        scanf("%d", &L.num[i]);
    }
}
int max_sum(Table L, int l, int r){
    cnt++;
    int sum1, sum2, sum3, sum4, mav3, mav4;
    if(l == r){
        if(L.num[l] < 0)
            return 0;
        else
            return L.num[l];
    }
    int mid = (l+r)>>1;
    sum1 = max_sum(L, l, mid);
    sum2 = max_sum(L, mid+1, r);
    sum3 = sum4 = 0, mav3 = mav4 = 0;
    for(int i = mid; i >= l; i--){
        sum3 += L.num[i];
        mav3 = max(mav3, sum3);
    }
    for(int i = mid+1; i <= r; i++){
        sum4 += L.num[i];
        mav4 = max(mav4, sum4);
    }
    int ans = 0;
    ans = max(sum1, sum2);
    ans = max(ans, mav3+mav4);
    return ans;
}
void delete_table(Table &L){
    delete []L.num;
}


/*************************************************** User name: Result: Accepted Take time: 12ms Take Memory: 308KB Submit time: 2017-09-20 20:12:31 ****************************************************/

顺序表应用8:最大子段和之动态规划法
Time Limit: 5MS Memory Limit: 500KB

Problem Description
给定n(1<=n<=100000)个整数(可能为负数)组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。当所给的整数均为负数时定义子段和为0,依此定义,所求的最优值为: Max{0,a[i]+a[i+1]+…+a[j]},1<=i<=j<=n。 例如,当(a[1],a[2],a[3],a[4],a[5],a[6])=(-2,11,-4,13,-5,-2)时,最大子段和为20。
注意:本题目要求用动态规划法求解,只需要输出最大子段和的值。

Input
第一行输入整数n(1<=n<=100000),表示整数序列中的数据元素个数;
第二行依次输入n个整数,对应顺序表中存放的每个数据元素值。

Output
输出所求的最大子段和

Example Input
6
-2 11 -4 13 -5 -2

Example Output
20

Hint

Author

以下为Accepted代码

#include 
#include 
#include 

using namespace std;

struct Table{
    int size;
    int *num;
};

void build_table(Table &L, int n);/*建表*/
int max_sum(Table L);/*动态规划法求最大子段和*/
void delete_table(Table &L);/*释放内存*/

int main(){
    int n;
    Table test;
    while(~scanf("%d", &n)){
        build_table(test, n);
        printf("%d\n", max_sum(test));
        delete_table(test);
    }
    return 0;
}
void build_table(Table &L, int n){
    L.size = n;
    L.num = new int[n+4];
    for(int i = 1; i <= n; i++)
        scanf("%d", &L.num[i]);
}
int max_sum(Table L){
    int sum = 0, ans = 0;
    for(int i = 1; i <= L.size; i++){
        sum += L.num[i];/*以L.num[i]作为最后一位的子段和*/
        if(sum < 0)
            sum = 0;
        ans = max(ans, sum);
    }
    return ans;
}
void delete_table(Table &L){
    delete L.num;
}


/*************************************************** User name: Result: Accepted Take time: 8ms Take Memory: 308KB Submit time: 2017-09-20 20:31:41 ****************************************************/

你可能感兴趣的:(SDUT专题整理——顺序表)