A - 顺序表应用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
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
#include<stdio.h>
#include<stdlib.h>
#define maxsize 200010
typedef int elemtype;
typedef struct
{
elemtype *elem;
int listlength;
int listsize;
}S;
int intlist(S &l)
{
l.elem=(elemtype *)malloc(maxsize *sizeof(elemtype));
if(!l.elem)
{
return -1;
}
l.listlength=0;
l.listsize=maxsize;
return 0;
}
void creatlist(S &l,int n)
{
for(int i=0;i<n;i++)
{
scanf("%d",&l.elem[i]);
}
l.listlength=n;
}
void deletelist(S &l)
{
for(int i=0;i<l.listlength-1;i++)
{
for(int j=i+1;j<l.listlength;j++)
{
if(l.elem[i]==l.elem[j])
{
l.listlength--;
for(int k=j;k<l.listlength;k++)
{
l.elem[k]=l.elem[k+1];
}
j--;
}
}
}
}
void printlist(S &l)
{
for(int i=0;i<l.listlength-1;i++)
{
printf("%d ",l.elem[i]);
}
printf("%d\n",l.elem[l.listlength-1]);
}
void clearlist(S &l)
{
if(l.listlength)
{
l.listlength=0;
l.listsize=maxsize;
}
}
int main()
{
int m;
S l;
scanf("%d",&m);
while(m--)
{
int n;
scanf("%d",&n);
intlist(l);
creatlist(l,n);
deletelist(l);
printlist(l);
clearlist(l);
}
}
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
#include<stdio.h>
#include<stdlib.h>
#define maxsize 200010
typedef int elemtype;
typedef struct
{
elemtype *elem;
int listlength;
int listsize;
}S;
int intlist(S &l)
{
l.elem=(elemtype *)malloc(maxsize *sizeof(elemtype));
if(!l.elem)
{
return -1;
}
l.listlength=0;
l.listsize=maxsize;
return 0;
}
void creatlist(S &l,int n)
{
for(int i=0;i<n;i++)
{
scanf("%d",&l.elem[i]);
}
l.listlength=n;
}
void mergelist(S &l,S &l1)
{
int k=0;
for(int i=0;i<l.listlength;i++)
{
int c=0;
for(int j=0;j<k;j++)
{
if(l.elem[i]==l.elem[j])
{
c=1;
break;
}
}
if(!c)
{
l1.elem[k++]=l.elem[i];
}
}
l1.listlength=k;
}
void printlist(S &l)
{
for(int i=0;i<l.listlength-1;i++)
{
printf("%d ",l.elem[i]);
}
printf("%d\n",l.elem[l.listlength-1]);
}
void clearlist(S &l)
{
if(l.listlength)
{
l.listlength=0;
l.listsize=maxsize;
}
}
int main()
{
int m;
S l,l1;
scanf("%d",&m);
while(m--)
{
int n;
scanf("%d",&n);
intlist(l);
intlist(l1);
creatlist(l,n);
mergelist(l,l1);
printlist(l1);
clearlist(l);
clearlist(l1);
}
}
C - 顺序表应用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
#include<stdio.h>
#include<stdlib.h>
#define maxsize 200001
typedef int elemtype;
typedef struct
{
elemtype *elem;
int listlength;
int listsize;
}S;
int intlist(S &l)
{
l.elem=(elemtype *)malloc(maxsize * sizeof(elemtype));
if(!l.elem)
{
return -1;
}
l.listlength=0;
l.listsize=maxsize;
return 0;
}
void creatlist(S &l, int n)
{
for(int i=0;i<n;i++)
{
scanf("%d",&l.elem[i]);
}
l.listlength=n;
}
void mergelist(S &l,int start,int end,int mid)
{
for(int i=0;i<mid;i++)
{
int t=l.elem[start];
l.elem[start++]=l.elem[end];
l.elem[end--]=t;
}
}
void printlist(S &l)
{
for(int i=0;i<l.listlength;i++)
{
printf("%d ",l.elem[i]);
}
printf("\n");
}
int main()
{
int n,m,t;
S l;
scanf("%d",&n);
intlist(l);
creatlist(l,n);
scanf("%d",&t);
while(t--)
{
scanf("%d",&m);
mergelist(l,0,n-1,n/2);
mergelist(l,0,n-m-1,(n-m)/2);
mergelist(l,n-m,n-1,m/2);
printlist(l);
}
return 0;
}
D - 顺序表应用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
#include<stdio.h>
#include<stdlib.h>
#define maxsize 200001
typedef int elemtype;
typedef struct
{
elemtype *elem;
int listlength;
int listsize;
}S;
int intlist(S &l)
{
l.elem=(elemtype *)malloc(maxsize *sizeof(elemtype));
if(!l.elem)
{
return -1;
}
l.listlength=0;
l.listsize=maxsize;
return 0;
}
void creatlist(S &l,int n)
{
for(int i=0;i<n;i++)
{
scanf("%d",&l.elem[i]);
}
l.listlength=n;
}
void mergelist(S &l1,S &l2,S &l)
{
int i,j,k;
i=0,j=0,k=0;
while(i<l1.listlength && j<l2.listlength)
{
if(l1.elem[i]>l2.elem[j])
{
l.elem[k++]=l2.elem[j];
j++;
}
else
{
l.elem[k++]=l1.elem[i];
i++;
}
}
while(i<l1.listlength)
{
l.elem[k++]=l1.elem[i];
i++;
}
while(j<l2.listlength)
{
l.elem[k++]=l2.elem[j];
j++;
}
l.listlength=k;
}
void printlist(S &l)
{
for(int i=0;i<l.listlength;i++)
{
printf("%d ",l.elem[i]);
}
}
int main()
{
int m,n;
S l1,l2,l;
scanf("%d%d",&m,&n);
intlist(l1);
intlist(l2);
intlist(l);
creatlist(l1,m);
creatlist(l2,n);
mergelist(l1,l2,l);
printlist(l);
return 0;
}
E - 顺序表应用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
#include<stdio.h>
#include<stdlib.h>
#define maxsize 220000
typedef int elemtype;
typedef struct
{
elemtype *elem;
int listlength;
int listsize;
}S;
int intlist(S &l)
{
l.elem=(elemtype *)malloc(maxsize * sizeof(elemtype));
if(!l.elem)
{
return -1;
}
l.listlength=0;
l.listsize=maxsize;
return 0;
}
void creatlist(S &l,int n)
{
for(int i=0;i<n;i++)
{
scanf("%d",&l.elem[i]);
}
l.listlength=n;
}
void findlist(S & l, int s, int t, int key)
{
int low = s, high = t;
if(s <= t)
{
int mid = low + (high - low) / 2;
if(l.elem[mid] == key)
{
printf("%d\n",mid+1);
return;
}
if(l.elem[mid] > key)
findlist(l, low, mid - 1, key);
else
findlist(l, mid + 1, high, key);
}
if(s > t)
{
printf("No Found!\n");
}
}
int main()
{
int n,m,t;
S l;
scanf("%d",&n);
intlist(l);
creatlist(l,n);
scanf("%d",&m);
while (m--)
{
scanf("%d",&t);
findlist(l,0,n-1,t);
}
return 0;
}
H - 数据结构上机测试1:顺序表的应用
Description
在长度为n(n<1000)的顺序表中可能存在着一些值相同的“多余”数据元素(类型为整型),编写一个程序将“多余”的数据元素从顺序表中删除,使该表由一个“非纯表”(值相同的元素在表中可能有多个)变成一个“纯表”(值相同的元素在表中只能有一个)。
Input
第一行输入表的长度n;
第二行依次输入顺序表初始存放的n个元素值。
Output
第一行输出完成多余元素删除以后顺序表的元素个数;
第二行依次输出完成删除后的顺序表元素。
Sample
Input
12
5 2 5 3 3 4 2 5 7 5 4 3
Output
5
5 2 3 4 7
#include<stdio.h>
#include<stdlib.h>
#define maxsize 100010
typedef int elemtype;
typedef struct
{
elemtype *elem;
int listlength;
int listsize;
}S;
int intlist(S &l)
{
l.elem=(elemtype *)malloc(maxsize * sizeof(elemtype));
if(!l.elem)
{
return -1;
}
l.listlength=0;
l.listsize=maxsize;
return 0;
}
void creatlist(S &l,int n)
{
for(int i=0;i<n;i++)
{
scanf("%d",&l.elem[i]);
}
l.listlength=n;
}
void deletelist(S &l)
{
for(int i=0;i<l.listlength-1;i++)
{
for(int j=i+1;j<l.listlength;j++)
{
if(l.elem[i]==l.elem[j])
{
l.listlength--;
for(int k=j;k<l.listlength;k++)
{
l.elem[k]=l.elem[k+1];
}
j--;
}
}
}
}
void printlist(S &l)
{
printf("%d\n",l.listlength);
for(int i=0;i<l.listlength;i++)
{
printf("%d ",l.elem[i]);
}
}
int main()
{
int n;
S l;
scanf("%d",&n);
intlist(l);
creatlist(l,n);
deletelist(l);
printlist(l);
return 0;
}
I - 顺序表应用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 maxsize 100010
int n,m;
typedef int elemtype;
typedef struct
{
elemtype *elem;
int listlength;
int listsize;
}S;
int intlist(S &l)
{
l.elem=(elemtype *)malloc(maxsize * sizeof(elemtype));
if(!l.elem)
{
return -1;
}
l.listlength=0;
l.listsize=maxsize;
return 0;
}
void creatlist(S &l,int n)
{
for(int i=0;i<n;i++)
{
scanf("%d",&l.elem[i]);
}
l.listlength=n;
}
void movelist(S &l)
{
for(int i=0;i<m;i++)
{
l.elem[i+n]=l.elem[i];
}
l.listlength+=m;
}
void printlist(S &l)
{
for(int i=m;i<l.listlength-1;i++)
{
printf("%d ",l.elem[i]);
}
printf("%d\n",l.elem[l.listlength-1]);
}
int main()
{
int t;
S l,l1;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
intlist(l);
creatlist(l,n);
movelist(l);
printlist(l);
}
return 0;
}
F - 顺序表应用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
#include<stdio.h>
#include<stdlib.h>
#define maxsize 99999
typedef int elemtype;
typedef struct
{
elemtype *elem;
int listlength;
int listsize;
}S;
int intlist(S &l)
{
l.elem=(elemtype *)malloc(maxsize * sizeof(elemtype));
if(!l.elem)
{
return -1;
}
l.listlength=0;
l.listsize=maxsize;
return 0;
}
void creatlist(S &l,int n)
{
for(int i=0;i<n;i++)
{
scanf("%d",&l.elem[i]);
}
l.listlength=n;
}
int cnt = 0,sum = 0;
int findmax(S &l,int start,int end)
{
cnt++;
if(start==end)
{
if(l.elem[start]>0)
{
sum = l.elem[start];
}
else
{
sum = 0;
}
}
else
{
int lsum=0,rsum=0;
int mid=(start+end)/2;
lsum=findmax(l,start,mid);
rsum=findmax(l,mid+1,end);
int tsum=0,ls=0,rs=0;
for(int i=mid;i>=start;i--)
{
tsum+=l.elem[i];
if(tsum>ls)
{
ls = tsum;
}
}
tsum=0;
for(int i=mid+1;i<end;i++)
{
tsum+=l.elem[i];
if(tsum>rs)
{
rs = tsum;
}
}
sum = rs + ls;
if(lsum>sum)
{
sum = lsum;
}
if(rsum>sum)
{
sum = rsum;
}
}
return sum;
}
int main()
{
S l;
int n;
scanf("%d",&n);
intlist(l);
creatlist(l,n);
int smax=findmax(l,0,n-1);
printf("%d %d",smax,cnt);
return 0;
}
G - 顺序表应用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
#include<stdio.h>
#include<stdlib.h>
#define maxsize 50010
typedef int elemtype;
typedef struct
{
elemtype *elem;
int listlength;
int listsize;
}S;
int intlist(S &l)
{
l.elem=(elemtype *)malloc(maxsize * sizeof(elemtype));
if(!l.elem)
{
return -1;
}
l.listlength=0;
l.listsize=maxsize;
return 0;
}
void creatlist(S &l,int n)
{
for(int i=0;i<n;i++)
{
scanf("%d",&l.elem[i]);
}
l.listlength=n;
}
int findmax(S &l)
{
int sum = 0, tsum = 0;
for(int i = 0; i < l.listlength; i++)
{
if(tsum + l.elem[i] > 0)
{
tsum = tsum + l.elem[i];
if(tsum > sum)
sum = tsum;
}
else
tsum = 0;
}
return sum;
}
int main()
{
S l;
int n;
scanf("%d",&n);
intlist(l);
creatlist(l,n);
int smax=findmax(l);
printf("%d",smax);
return 0;
}