Problem 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
Sample Output
6 9 8 5 9 8 7 6 5 1 2 3 4 5
Hint
Source
第1种算法(建表算法):
大致思想是在原表的基础上再建一次表,然后比较新表和原表上的元素,如果新表中没有原表的元素就把这个原表的元素放到这个新表里面去。具体代码如下:
具体示意图:
以6 9 6 8 9 为例
6 | 9 | 6 | 8 | 9 |
黄箭头是新表,蓝箭头是原表。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int a[10001] ;
int n ;
int cmd ;
void check(int *a)
{
int i , j ;
int flag ;
for( i = 0 ; i<n ; i++ )
{
flag = 0 ;
for(j = 0 ; j < cmd ; j++)
{
if(a[i]==a[j])
{
flag = 1 ;
break ;
}
}
if(!flag)
{
a[cmd++] = a[i] ;
}
}
}
void print(int *a)
{
int i ;
for(i = 0 ; i<cmd ; i++)
{
if(i==cmd-1)
{
printf("%d\n",a[i]) ;
}
else
printf("%d ",a[i]) ;
}
return ;
}
int main()
{
int t ;
int i ;
scanf("%d",&t) ;
while(t--){
scanf("%d",&n) ;
cmd = 0 ;
for( i = 0 ; i < n ; i++)
scanf("%d",&a[i]) ;
check(a) ;
print(a) ;
}
return 0 ;
}
代码2:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAXSIZE 10001 //定义顺序表最大长长度
//定义顺序表的基本结构
typedef struct
{
int *elem ;
int length ;
}Sqlist ;
Sqlist creat(Sqlist l ,int m)
{
int i;
l.elem = (Sqlist*)malloc(MAXSIZE*sizeof(Sqlist)) ;
l.length = m ;
for(i = 0; i<m ; i++)
{
scanf("%d",&l.elem[i]);
}
return l ;
}
Sqlist Insert(Sqlist l)
{
int cmd = 0 ; //记录新表中的元素个数
int tag = 1; //标识变量
int i , j ;
for(i = 0 ; i<l.length ;i++)
{
tag = 1;
for(j = 0; j<cmd ;j++)
{
if(l.elem[i] == l.elem[j])
{
tag = 0 ;
break ;
}
}
if(tag)
{
l.elem[cmd++] = l.elem[i] ;
}
}
l.length = cmd ;
return l ;
}
void show(Sqlist l)
{
int i ;
for( i= 0 ; i< l.length ; i++)
{
if(i == 0)
{
printf("%d",l.elem[i]) ;
}
else printf(" %d",l.elem[i]) ;
}
printf("\n") ;
}
int main()
{
int n;
scanf("%d",&n) ;
while(n--)
{
int m ;
scanf("%d",&m) ;
Sqlist l ;
l = creat(l,m) ; //建立顺序表
l = Insert(l) ; //建表算法删数
show(l) ;
}
return 0 ;
}
第2种算法(移位算法):
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int a[10001] ;
int n ;
void ni(int *a)
{
int i ,j ;
int t;
for( i = 0 ; i < n ; i++)
{
for( j = i+1 ; j< n; j++)
{
if(a[i]==a[j] )
{
for(t = j ;t< n-1 ; t++)
a[t] = a[t+1] ;
n-- ;
j-- ;/************特别注意这一步*************/
}
}
}
}
void print(int *a)
{
int i;
for( i =0 ; i< n ;i++)
{
if(i == n-1 )
{
printf("%d\n",a[i]) ;
}
else printf("%d ",a[i]) ;
}
return ;
}
int main()
{
int t ;
int i ;
scanf("%d",&t) ;
while(t--)
{
scanf("%d",&n) ;
for( i = 0 ; i < n ; i++)
scanf("%d",&a[i]) ;
ni(a) ;
print(a) ;
}
return 0 ;
}
代码2(本代码使用的是动态创建顺序表):
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAXSIZE 10001 //定义顺序表的最大长度
//定义顺序表
typedef struct
{
int *elem ; //定义一个空间存放基址
int length ; //记录顺序表的当前长度。
}Sqlist;
Sqlist creat(Sqlist l,int m)
{
int i;
l.elem = (Sqlist*)malloc(MAXSIZE*sizeof(Sqlist)) ;
l.length = 0 ;
for( i = 0; i<m ; i++)
{
scanf("%d",&l.elem[i]) ;
}
l.length = m ;
return l ;
}
Sqlist del(Sqlist l)
{
int i, j;
int k ;
//从第一个元素开始遍历,如果遇到相同的就删掉
for(i = 0 ; i<l.length ; i++)
{
for(j = i+1; j<l.length ; j++)
{
if(l.elem[i] == l.elem[j])
{
for( k = j ; k<l.length - 1 ; k++)
{
l.elem[k] = l.elem[k+1] ;
}
l.length -- ;
j-- ; //特别容易出错的地方
}
}
}
return l ;
}
void show(Sqlist l)
{
int i ;
for( i = 0 ; i< l.length ; i++)
{
if(i == 0)
{
printf("%d",l.elem[i]) ;
}
else printf(" %d",l.elem[i]) ;
}
printf("\n") ;
}
int main()
{
int n ;
scanf("%d",&n) ;
while(n --)
{
int m ;
scanf("%d",&m) ;
Sqlist l ;//定义顺序表
l = creat(l,m) ; //创建顺序表
l = del(l) ; //删除重复元素的构成新的顺序表
show(l) ; //输出顺序表
}
return 0 ;
}
代码 3(本代码使用的是静态创建顺序表)
/**********
数据结构 顺序表练习(存储结构)
A - 顺序表应用1:多余元素删除之移位算法
时间:2021 - 5 - 4
**************/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MaxSize 10001
// 第一种方法使用静态分配的方式
typedef struct {
int data[MaxSize]; //存储数据
int length ; //记录当前顺序表的表长
}SqList ;
SqList ListDelete(SqList sqlist, int pos){
// pos 是要删除位置 下标
// 因为是删除当前位置 所以要把当前位置后的每一个都要向前移动一位(即用后一位来覆盖前一位)
int i = pos +1; // 记录第一个要移动的坐标
for(;i<sqlist.length ;i++){
sqlist.data[i-1] = sqlist.data[i] ;
}
// 因为删除了一个元素 ,所以 sqlist 的长度要变化
sqlist.length = sqlist.length-1;
return sqlist ;
}
SqList InitList(SqList sqlist,int left ,int right){ // left 代表最左边的 元素 , right 代表最右端的元素
//首先 将表长 给 sqlist
sqlist.length = right ;
int i ;
// 获取重键盘上输入的数据
for( i = 0; i<sqlist.length ; i++){
scanf("%d",&sqlist.data[i]) ;
}
int j;
// 用双重 循环 来 筛选 重复数据,并 将其删除
for(i = 0; i < sqlist.length - 1; i++){
for( j = i+1 ; j<sqlist.length ; j++){
if(sqlist.data[j] == sqlist.data[i]){
sqlist =ListDelete(sqlist,j) ; // 将后面出现的数字删除
j = j -1 ; // 由于是移位删除,删除时导致原来后一位移动到当前位,所以仍需对j这位置进行一次判断
}
}
}
return sqlist ;
}
void show(SqList sqlist){
// 按照指定格式 输出数据
int i ;
for(i = 0 ; i< sqlist.length ;i++){
// 为了消除最后的空格
if(i == sqlist.length -1 ){
printf("%d\n",sqlist.data[i]) ;
}
else {
printf("%d ",sqlist.data[i]) ;
}
}
}
int main(){
int n ; // 记录输入的组数
scanf("%d",&n) ;
int i = 0 ; // 分别处理每一组的数据
for(; i< n; i++){
int m ; // 记录每个每个顺序表的存储的数据
scanf("%d",&m);
SqList sqlist ;
sqlist = InitList(sqlist,0,m) ; // 初始化 顺序表 同时在初始化时就删除重复的元素
show(sqlist) ; // 显示 删除重复之后的元素
}
return 0 ;
}