《数据结构》专题1--顺序表

C - 顺序表应用1:多余元素删除之移位算法

Description

一个长度不超过10000数据的顺序表,可能存在着一些值相同的“多余”数据元素(类型为整型),编写一个程序将“多余”的数据元素从顺序表中删除,使该表由一个“非纯表”(值相同的元素在表中可能有多个)变成一个“纯表”(值相同的元素在表中只保留第一个)。

要求:

1、必须先定义线性表的结构与操作函数,在主函数中借助该定义与操作函数调用实现问题功能;

2、本题的目标是熟悉顺序表的移位算法,因此题目必须要用元素的移位实现删除;

Input

第一行输入整数n,代表下面有n行输入;

之后输入n行,每行先输入整数m,之后输入m个数据,代表对应顺序表的每个元素。

Output

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

Sample

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

Output 

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

Hint

#include <stdio.h>
#include <stdlib.h>
#define max 10001
struct node
{
    int data[max];
    int length;
};
void init(struct node *p) //线性表初始化
{
    p->length=0;//指针变量 成员引用 用“->”
}
void putin(struct node *p,int k) //输入数据
{
    int i;
    p->length=k;
    for(i=1; i<=k; i++)
    {
        scanf("%d",&p->data[i]);
    }
}
void delete_same(struct node *p) //根据题目要求删除重复元素
{
    int i,j,k;
    for(i=1; i<=p->length; i++)
    {
        for(j=i+1; j<=p->length; j++)
        {
            if(p->data[i]==p->data[j])
            {
                for(k=j; k<=p->length; k++) //利用K记录重复元素的位置
                {
                    p->data[k]=p->data[k+1];//通过元素移位将重复元素删除
                }
                p->length--;//元素删除后 注意:线性表长度的改变
                j--;// 注意细节
            }
        }
    }

}
void putout(struct node *p) //输出+格式控制
{
    int i;
    for(i=1; i<=p->length; i++)
    {
        if(i==p->length)
            printf("%d\n",p->data[i]);
        else printf("%d ",p->data[i]);
    }

}
int main()
{
    struct node *a;
    a=(struct node *)malloc(sizeof(struct node));
    init(a);
    int n,m;
    scanf("%d",&n);
    while(n--)
    {
        scanf("%d",&m);
        putin(a,m);
        delete_same(a);
        putout(a);
    }

    return 0;
}

B - 顺序表应用2:多余元素删除之建表算法

Description

一个长度不超过10000数据的顺序表,可能存在着一些值相同的“多余”数据元素(类型为整型),编写一个程序将“多余”的数据元素从顺序表中删除,使该表由一个“非纯表”(值相同的元素在表中可能有多个)变成一个“纯表”(值相同的元素在表中只保留第一个)。

要求:

1、必须先定义线性表的结构与操作函数,在主函数中借助该定义与操作函数调用实现问题功能;

2、本题的目标是熟悉在顺序表原表空间基础上建新表的算法,要在原顺序表空间的基础上完成完成删除,建表过程不得开辟新的表空间;

3、不得采用原表元素移位删除的方式。

Input

第一行输入整数n,代表下面有n行输入;

之后输入n行,每行先输入整数m,之后输入m个数据,代表对应顺序表的每个元素。

Output

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

Sample

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

Output 

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

Hint

#include <stdio.h>
#include <stdlib.h>
#define max 10001
struct node
{
    int data[max];
    int length;
};
void init(struct node *p) //线性表初始化
{
    p->length=0;//指针变量 成员引用 用“->”
}
void putin(struct node *p,int k) //输入数据
{
    int i;
    p->length=k;
    for(i=1; i<=k; i++)
    {
        scanf("%d",&p->data[i]);
    }
}
void delete_same(struct node *p) //根据题目要求删除重复元素 非 移位法
{
    int i,j;
    int t=1;
    for(i=1; i<=p->length; i++)
    {
        int flag=0;
        for(j=1; j<t; j++)
        {
            if(p->data[i]==p->data[j])
            {
                flag=1;
                break;
            }
        }
        if(flag==0)//如果无重复元素 将不重复的元素覆盖新表 (即不用开辟新空间)
        {

            p->data[t]=p->data[i];
            t++;
        }
    }
    p->length=t-1;
}

void putout(struct node *p) //输出+格式控制
{
    int i;
    for(i=1; i<=p->length; i++)
    {
        if(i==p->length)
            printf("%d\n",p->data[i]);
        else printf("%d ",p->data[i]);
    }

}
int main()
{
    struct node *a;
    a=(struct node *)malloc(sizeof(struct node));
    init(a);
    int n,m;
    scanf("%d",&n);
    while(n--)
    {
        scanf("%d",&m);
        putin(a,m);
        delete_same(a);
        putout(a);
    }

    return 0;
}

D - 顺序表应用3:元素位置互换之移位算法

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)个元素交换后的结果

Sample

Input 

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

Output 

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

Hint

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

#include <stdio.h>
#include <stdlib.h>
#define max 1000001
struct node
{
    int data[max];
    int length;
};
void init(struct node *p) //线性表初始化
{
    p->length=0;//指针变量 成员引用 用“->”
}
void putin(struct node *p,int k,int l) //输入数据
{
    int i;
    p->length=k;
    for(i=1; i<=k; i++)
    {
        scanf("%d",&p->data[i]);
    }
    for(i=1; i<=l; i++)
    {
        p->data[k+i]=p->data[i];
    }
}

void putout(struct node *p,int l) //输出+格式控制
{
    int i;
    for(i=l+1; i<=p->length+l; i++)
    {
        if(i==p->length+l)
            printf("%d\n",p->data[i]);
        else printf("%d ",p->data[i]);
    }

}
int main()
{
    int l;
    struct node *a;
    a=(struct node *)malloc(sizeof(struct node));
    int n,m;
    scanf("%d",&n);
    while(n--)
    {
        init(a);
        scanf("%d%d",&m,&l);
        putin(a,m,l);
        putout(a,l);
    }

    return 0;
}

顺序表应用4:元素位置互换之逆置算法

Description

一个长度为len(1<=len<=1000000)的顺序表,数据元素的类型为整型,将该表分成两半,前一半有m个元素,后一半有len-m个元素(1<=m<=len),设计一个时间复杂度为O(N)、空间复杂度为O(1)的算法,改变原来的顺序表,把顺序表中原来在前的m个元素放到表的后段,后len-m个元素放到表的前段。

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

Input

第一行输入整数n,代表下面有n行输入;

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

Output

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

Sample

Input 

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

Output 

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

Hint

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

#include <stdio.h>
#include <stdlib.h>
#define max 10001
struct node
{
    int data[max];
    int length;
};
void init(struct node *p) //线性表初始化
{
    p->length=0;//指针变量 成员引用 用“->”
}
void putin(struct node *p,int k) //输入数据
{
    int i;
    p->length=k;
    for(i=1; i<=k; i++)
    {
        scanf("%d",&p->data[i]);
    }

}
void nizhi(struct node *p,int s,int l)
{
    int i,j;
    int t;
    for(i=s,j=l; i<j; i++,j--)
    {
        t=p->data[j];
        p->data[j]=p->data[i];
        p->data[i]=t;
    }
}
void putout(struct node *p) //输出+格式控制
{
    int i;
    for(i=1; i<=p->length; i++)
    {
        if(i==p->length)
            printf("%d\n",p->data[i]);
        else printf("%d ",p->data[i]);
    }

}
int main()
{
    int l;
    struct node *a;
    a=(struct node*)malloc(sizeof(struct node));
    int n,m;
    scanf("%d",&n);
    while(n--)
    {
        init(a);
        scanf("%d%d",&m,&l);
        putin(a,m);
        nizhi(a,1,m);//将整个数组逆置 L位置前后的数据进行整体的逆置交换
        nizhi(a,1,m-l);//将L位置前的数据逆置 局部恢复之前正确的顺序      注意:边界!
        nizhi(a,m-l+1,m);//将L位置后的数据逆置  局部恢复之前正确的顺序
        putout(a);
    }

    return 0;
}

I - 顺序表应用4-2:元素位置互换之逆置算法(数据改进)

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行,每行依次输出本次交换完成后顺序表里所有元素。

Sample

Input 

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

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

#include <stdio.h>
#include <stdlib.h>
#define max 100001
struct node
{
    int data[max];
    int length;
};
void init(struct node *p) //线性表初始化
{
    p->length=0;//指针变量 成员引用 用“->”
}
void putin(struct node *p,int k) //输入数据
{
    int i;
    p->length=k;
    for(i=1; i<=k; i++)
    {
        scanf("%d",&p->data[i]);
    }
}
void nizhi(struct node *p,int s,int l)
{
    int i,j;
    int t;
    for(i=s,j=l; i<j; i++,j--)
    {
        t=p->data[j];
        p->data[j]=p->data[i];
        p->data[i]=t;
    }
}
void putout(struct node *p) //输出+格式控制
{
    int i;
    for(i=1; i<=p->length; i++)
    {
        if(i==p->length)
            printf("%d\n",p->data[i]);
        else printf("%d ",p->data[i]);
    }

}
int main()
{
    struct node *a;
    a=(struct node*)malloc(sizeof(struct node));
    int m;
    int t;
    scanf("%d",&m);
    init(a);
    putin(a,m);
    scanf("%d",&t);
    while(t--)
    {
        int l;
        scanf("%d",&l);
        nizhi(a,1,m);
        nizhi(a,1,m-l);
        nizhi(a,m-l+1,m);
        putout(a);
    }


    return 0;
}

若想用C++还不超时的话(80ms),则注意“ios::sync_with_stdio(false);”语句的添加。

#include <bits/stdc++.h>
#define max 1000001
using namespace std;

struct node
{
    int data[max];
    int length;
};
void init(struct node *p) //线性表初始化
{
    p->length=0;//指针变量 成员引用 用“->”
}
void putin(struct node *p,int k) //输入数据
{
    int i;
    p->length=k;
    for(i=1; i<=k; i++)
    {
       cin>>p->data[i];
    }
}
void nizhi(struct node *p,int s,int l)
{
    int i,j;
    int t;
    for(i=s,j=l; i<j; i++,j--)
    {
        t=p->data[j];
        p->data[j]=p->data[i];
        p->data[i]=t;
    }
}
void putout(struct node *p) //输出+格式控制
{
    int i;
    for(i=1; i<=p->length; i++)
    {
        if(i==p->length)
           cout<<p->data[i]<<endl;
        else  cout<<p->data[i]<<" ";
    }

}
int main()
{ios::sync_with_stdio(false);//这段语句可以来打消iostream的输入、输出缓存 
//可以节省许多时间 使效率与scanf与printf相差无几
    struct node *a;
    a=(struct node*)malloc(sizeof(struct node));
    int m;
    int t;
   cin>>m;
    init(a);
    putin(a,m);
    cin>>t;
    while(t--)
    {
        int l;
        cin>>l;
        nizhi(a,1,m);
        nizhi(a,1,m-l);
        nizhi(a,m-l+1,m);
        putout(a);
    }


    return 0;
}

E - 顺序表应用5:有序顺序表归并

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所存放的元素。

Sample

Input 

5 3
1 3 5 6 9
2 4 10

Output 

1 2 3 4 5 6 9 10

Hint

#include <stdio.h>
#include <stdlib.h>
struct node
{
    int data;
    struct node *next;
}*head1,*head2,*head3;
struct node *creat(int n)
{
    struct node *p,*q,*head;
    head=(struct node *)malloc(sizeof(struct node));
    head->next=NULL;
    p=head;
    int i;
    for(i=1; i<=n; i++)
    {
        q=(struct node *)malloc(sizeof(struct node ));
        scanf("%d",&q->data);
        q->next=NULL;
        p->next=q;
        p=q;
    }
    return head;
}
struct node *merge(struct node *head3,struct node *head1,struct node *head2)
{
    struct node *p,*q,*r;
    r=head3;
    p=head1->next;
    q=head2->next;
    while(q&&p)
    {
        if(p->data>q->data)
        {
            r->next=q;
            r=q;
            q=q->next;
        }
        else
        {
            r->next=p;
            r=p;
            p=p->next;
        }
    }
    if(q)
        r->next=q;
    if(p)
        r->next=p;
    return head3;
}
void show(struct node *head)
{
    struct node *q;
    q=head->next;
    while(q)
    {
        if(q->next)
            printf("%d ",q->data);
        else printf("%d\n",q->data);
        q=q->next;
    }

}
int main()
{
    head3=(struct node *)malloc(sizeof(struct node));
    int n,m;
    scanf("%d%d",&n,&m);
    head1=creat(n);
    head2=creat(m);
    head3=merge(head3,head1,head2);
    show(head3);
    return 0;
}

顺序表应用6:有序顺序表查询

Description

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

Input

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

保证所有输入的数都在 int 范围内。

Output

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

Sample

Input 

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

Output 

4
No Found!
No Found!
10

Hint

#include <stdio.h>
#include <stdlib.h>
#define max 100001
struct node
{
    int data[max];
    int length;
};
void init(struct node *p) //线性表初始化
{
    p->length=0;//指针变量 成员引用 用“->”
}
void putin(struct node *p,int k) //输入数据
{
    int i;
    p->length=k;
    for(i=1; i<=k; i++)
    {
        scanf("%d",&p->data[i]);
    }
}
void  find(struct node *p,int x)//二分查找
{
	int low, high, m;
	low = 1;
	high = p->length;
	while (low <= high)
	{
		m = (low + high) / 2;
		if (x < p->data[m])
		{
			high = m - 1;
		}
		else if (x > p->data[m])
		{
			low = m + 1;
		}
		else
		{
			printf("%d\n", m );
			return ;
		}
	}
	printf("No Found!\n");
	return ;
}
int main()
{
    struct node *a;
    a=(struct node*)malloc(sizeof(struct node));
    int m;
    int t;
    scanf("%d",&m);
    init(a);
    putin(a,m);
    scanf("%d",&t);
    while(t--)
    {
        int l;
        scanf("%d",&l);
        find(a,l);
    }


    return 0;
}

顺序表应用7:最大子段和之分治递归法

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

一行输出两个整数,之间以空格间隔输出:

第一个整数为所求的最大子段和;

第二个整数为用分治递归法求解最大子段和时,递归函数被调用的总次数。

Sample

Input 

6
-2 11 -4 13 -5 -2

Output 

20 11

Hint

#include<stdio.h>
int k=0;
int fenzhi(int a[],int l,int r)//关键代码
{
    int sum = 0,lsum = 0,rsum = 0,i;
    k++;
    if(l == r)
    {
        if(a[l]>0)
            sum = a[l];
        else
            sum = 0;
    }
    else
    {
        int mid = (l+r)/2;
        lsum = fenzhi(a,l,mid);
        rsum = fenzhi(a,mid+1,r);
        int s1=0,s2=0,s3=0;
        for(i=mid;i>=l;i--)
        {
            s3+=a[i];
            if(s3>s1) s1 = s3;
        }
        
        s3=0;
        for(i=mid+1;i<=r;i++)
        {
            s3+=a[i];
           if(s3>s2) s2 = s3;
        }
        
        sum=s1+s2;
        if(lsum>sum) sum=lsum;
        if(rsum>sum) sum=rsum;
    }
    return sum;
}
int main()
{
    int n,a[50010],t,i;
    scanf("%d",&n);
    for(i=0; i<n; i++)
    {
        scanf("%d",&a[i]);
    }
    t=fenzhi(a,0,n-1);//有返回值 所以用一变量来承接该值
    printf("%d %d\n",t,k);
    return 0;

}

顺序表应用8:最大子段和之动态规划法

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

输出所求的最大子段和

Sample

Input 

6
-2 11 -4 13 -5 -2

Output 

20

Hint

#include <stdio.h>
#include <stdlib.h>
#define max 100001
struct node
{
    int data[max];
    int length;
};
void init(struct node *p) //线性表初始化
{
    p->length=0;//指针变量 成员引用 用“->”
}
void putin(struct node *p,int k) //输入数据
{
    int i;
    p->length=k;
    for(i=1; i<=k; i++)
    {
        scanf("%d",&p->data[i]);
    }
}
int summax(struct node *p)
{
    int i;
    int summax=0;
    int sum=0;
    for(i=1; i<=p->length; i++)
    {
        sum+=p->data[i];
        if(sum<0)
            sum=0;
        if(sum>=summax)
            summax=sum;
    }
    return summax;
}
int main()
{
    struct node *a;
    a=(struct node*)malloc(sizeof(struct node));
    int m;
    int t;
    scanf("%d",&m);
    init(a);
    putin(a,m);
    t=summax(a);
    printf("%d\n",t);
    return 0;
}

 题解:因为小于0的记为0,所以遍历一遍顺序表就可以。如果当前的sum小于0,那么加上一定不是最优解,所以直接舍去,sum=0。比较sum和当前summax的大小,记录最大值为summax。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值