线性表是计算机最常见的一种数据结构.记录文件,数组,操作系统的进程队列等都是这种数据结构,它们或者用顺序存储结构,或者用链存储结构.下面介绍都是基于线性表的应用
数据查重是查看一个线性表中数据元素或其组成的数据项是否重复存储为多个结点.所线性表的存储结构不同,查重算法也不同;查重的目的不同,算法也不一样.就查重而言:清理性查重和统计性查重.
清理性查重:当有”相同”结点存储时只保留其中一个(通常是顺序表中的第一个),其余结点统统摘除
统计性查重:分别统计每一个节点在表中重复出现的次数
清理性查重的基本思想是:提取表中的一个结点(将保留在表中),用该结点的结点数据和其他结点进行比较,若有相同者将其从表中删除掉.这一操作从表中的第一个结点开始依次进行,直到终点的前继结点为止.注意:如果有重复结点的话,在对某一个结点实施查重后表的长度可能缩短.
统计性查重的基本思想与请理性查重基本一致.不同的是,不删除重复结点,只对重复结点计数.因此,要设置一个整数数组记录每一个结点在表中的重复次数.
在SequenStruct.c
#include
#define M 100
typedef struct {
int data[M];
int n;
}SEQUENLIST;
在Algorithm.h写出方法声明
/*
打印顺序表中数据元素
*/
void printSequenList(SEQUENLIST A);
/*
基于顺序表的查重算法:对无序的顺序表进行查重,当然也适用于有序的顺序表
*/
SEQUENLIST chzz(SEQUENLIST A);
在Algorithm.c中实现此方法
#include "Algorithm.h"
void printSequenList(SEQUENLIST A){
printf("sequen={");
printf("{");
int isFrist=0;
for(int i=0;iif(isFrist==0){
printf("%d",A.data[i]);
isFrist=1;
}else{
printf(",%d",A.data[i]);
}
}
printf("},%d",A.n);
printf("}\n");
}
/*
数据查重:无序的顺序表进行查重
*/
SEQUENLIST chzz(SEQUENLIST A){
//1.查看数据元素,如果n<=1那么就不需要查重
if(A.n<=1){
printf("数据查重成功\n");
return A;
}
int i,j,k;
//2.开始循环比较数据元素
for(i=0;i//3 第i个元素与后面的每个元素都比较j
j=i+1;
do{
//4.1如果两个元素相等,那么就执行删除操作
if(A.data[i]==A.data[j]){
k=j;
//4.2删除操作就是把j后面的元素都向前移动一个位置
for(;k1];
}
//4.3 A的长度自减-1,因为删除了相等的元素,那么此时j下表对用的位置是还未比较的元素(也就是没有删除前位置的下一个元素),所以j不用+1
A.n--;
}else{
//5.如果两个元素不相等,那么继续向下比较,j++
j++;
}
}while (jprintf("数据查重成功\n");
return A;
}
在main.c中的main方法(int main(int argc, const char * argv[]) {})调用此方法,并且进行判断
#include "Algorithm.h"
int main(int argc, const char * argv[]) {
//数据查重-无序
printf("数据查重-无序\n");
SEQUENLIST A={{1,2,4,8,2,5,12,45,6,8},10};
printSequenList(A);
A=chzz(A);
printSequenList(A);
printf("\n");
}
打印结果:
数据查重-无序
sequen={{1,2,4,8,2,5,12,45,6,8},10}
数据查重成功
sequen={{1,2,4,8,5,12,45,6},8}
注意:
1.在删除节点的时候,记得删除重复的结点后,计数器不能+1,因为此时要删除节点后的结点已经往前移动的一个位置,所以从当前位置继续比较即可.
2.删除节点(重复结点往前移动)的时候,最好用do{}while();循环,这样便于操作循环,容易控制计数器的变化.
在Algorithm.h写出方法声明
#include "SequenStruct.c"
/*
对有序的顺序表进行查重
*/
SEQUENLIST chzzByOrder(SEQUENLIST A);
在Algorithm.c中实现此方法
#include "Algorithm.h"
/*
数据查重:对有序的顺序表进行查重
*/
SEQUENLIST chzzByOrder(SEQUENLIST A){
//1.查看数据元素,如果n<=1那么就不需要查重
if(A.n<=1){
printf("数据查重成功\n");
return A;
}
int i,k;
//2.开始循环比较数据元素
do{
//3 第i个元素与相邻的元素进行比较就行,因为是有序的,
//3.1如果两个元素相等,那么就执行删除操作
if(A.data[i]==A.data[i+1]){
k=i+1;
//3.2删除操作就是把j后面的元素都向前移动一个位置
for(;k1];
}
//3.3 数据长度-1
A.n--;
//printSequenList(A);
}else{
i++;
}
}while (iprintf("数据查重成功\n");
return A;
}
在main.c中的main方法(int main(int argc, const char * argv[]) {})调用此方法,并且进行判断
#include "Algorithm.h"
int main(int argc, const char * argv[]) {
//数据查重-有序
printf("数据查重-有序\n");
SEQUENLIST B={{1,2,2,2,2,5,8,8,9,10},10};
printSequenList(B);
B=chzzByOrder(B);
printSequenList(B);
printf("\n");
}
打印结果:
数据查重-有序
sequen={{1,2,2,2,2,5,8,8,9,10},10}
数据查重成功
sequen={{1,2,5,8,9,10},6}
注意:对有序的顺序表进行查重,比无序的顺序表查重少一个循环操作(也就是当前节点没有必要和后面的节点都进行比较,只需要和相邻后面的节点进行比较即可),当然无序的操作查重也适用于有序的顺序表查重.
这是顺序表结构的应用,第一个例子:数据查重(清理性查重),大家有好的建议和好的书籍推荐,欢迎大家提出,共同进步.