SDUT OJ----数据结构----线性表习题

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;
}

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天行九歌。

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值