数据结构-线性表(顺序表)中删除相同的元素,只保留一个

这个专栏用于写一些数据结构中的例题,从线性表开始啦。

顺序表应用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

对于这道题,我们首先要掌握线性表中有关线性表的的基本操作。

(1)首先要定义一个结构体,来声明一个数组,一个顺序表的长度,代码如下:

#include <stdio.h>
#include <stdlib.h>
#define MAXIZE 10000    //定义数组大小为10000
typedef struct{         
    int data[MAXIZE];   //这个数组用于存储顺序表中的元素
    int length;         //这个则是标志当前顺序表的长度
}Seq;  

(2)定义一个函数,用来初始化顺序表,因为当前顺序表没有元素,把它的长度置为1即可。

void Init(Seq *head){
     head->length=0;
}

 (3)定义一个输入函数,我们用来输入顺序表中的元素。代码如下:

void Input(Seq *head,int x){//传入一个指针head,它代表当前的顺序表,x是我们要输入的元素数量
    for(int i=0;i<x;i++){
		scanf("%d",&head->data[i]);
    }
} 

(4)定义一个输出函数,用来打印顺序表中的每个元素

void Print(Seq head){
     for(int i=0;i<head.length;i++){
        printf("%d ",head.data[i]);
     }
     printf("\n");
}

(5)定义一个删除相同元素的函数,这个函数是做出来这道题的关键,我们先理清一下思路,要删除一个数组中相同的元素,我们需要从元素的起始位置即第一个元素开始依次与它后面的每一个元素都进行比较,然后从第二个元素依次和它后面的元素进行比较。所以我们就需要用到嵌套循环,那么如果我们找到相同的元素把它删除之后呢,我们需要把当前删除的元素后面剩余的 元素依次往前面移一位。就好比我们排队,队中间有人走出去的话,这个人前面的人不需要动,而它后面的人依次往前移动一位,并且长度减少了一。接下来我们来写代码。

void Delete(Seq *head){
     for(int i=0;i<head->length-1;i++){//第一层循环用于指向当前数组中的元素
        for(int j=i+1;j<head->length;j++){//第二层循环用于遍历当前元素后面的元素是否与这个元素的值相同
            if(head->data[i]==head->data[j]){ //如果在当前元素的后面找到了与它相同的元素
                for(int k=j;k<head->length-1;k++){//把当前位置后面的元素依次向前移动一位
                    head->data[k]=head->data[k+1];
                }
                head->length--; //当我们在删除一个相同的元素之后,顺序表的长度要减1
                j=i;            //把所有的元素都往前挪1位,让j都等于当前对比的这个元素,下一轮会加一,从当前对比的元素的下一位开始遍历 
            }
        }
     }
}

(6)当我们定义好我们需要的函数之后,我们就可以在主函数main中进行调用这些函数,用于实现我们的功能需求,之所以把各个功能写成一个函数,是因为这样的话我们可以方便使用,减少代码的冗余和重复性。用到时,只需要函数名就可以实现相应的功能,代码如下:

int main()
{
    Seq head;//声明一个顺序表的结构体变量 
    int n;
    scanf("%d",&n);     //第一行输入整数n,代表下面有n行输入;
    while(n>0){
        int x;
        Init(&head);     //调用初始化函数初始化结构体 
        scanf("%d",&x);  //每行先输入整数x,之后输入x个数据,代表对应顺序表的每个元素。 
        head.length=x;   
        Input(&head,x);  //输入函数 
        Delete(&head);   //删除函数 
        Print(head);     //打印操作之后的顺序表 
        n--;             //循环次数减1 
    }
    return 0;
}

(6)实现的结果如下:

 (7)整体代码如下:

#include <stdio.h>
#include <stdlib.h>
#define MAXIZE 10000
typedef struct{
    int data[MAXIZE];
    int length;
}Seq;
void Init(Seq *head){
     head->length=0;
}

void Delete(Seq *head){
     for(int i=0;i<head->length-1;i++){
        for(int j=i+1;j<head->length;j++){
            if(head->data[i]==head->data[j]){
                for(int k=j;k<head->length-1;k++){
                    head->data[k]=head->data[k+1];
                }
                head->length--;
                j=i;
            }
        }
     }
}
void Print(Seq head){
     for(int i=0;i<head.length;i++){
        printf("%d ",head.data[i]);
     }
     printf("\n");
}
void Input(Seq *head,int x){
    for(int i=0;i<x;i++){
		scanf("%d",&head->data[i]);
    }
} 
int main()
{
    Seq head;//声明一个顺序表的结构体变量 
    int n;
    scanf("%d",&n);     //第一行输入整数n,代表下面有n行输入;
    while(n>0){
        int x;
        Init(&head);     //调用初始化函数初始化结构体 
        scanf("%d",&x);  //每行先输入整数x,之后输入x个数据,代表对应顺序表的每个元素。 
        head.length=x;   
        Input(&head,x);  //输入函数 
        Delete(&head);   //删除函数 
        Print(head);     //打印操作之后的顺序表 
        n--;             //循环次数减1 
    }
    return 0;
}

总结:实现顺序表删除相同元素的方法不止这一种,我们声明一个顺序表也可以采用指针的方式,开辟一片空间,然后进行实现,思想一样,但是实现的方式不一样,如果有人有其他的方式实现,欢迎交流。我是参考的李春葆和高职高专计算机数据结构与算法那两本书。有关数据结构的所有算法思想以及实现过程,请参考我的数据结构与算法专栏。会逐步的更新内容。

  • 5
    点赞
  • 17
    收藏
  • 打赏
    打赏
  • 0
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:数字20 设计师:CSDN官方博客 返回首页
评论

打赏作者

AI学习的我

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

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

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

打赏作者

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

抵扣说明:

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

余额充值