集合的顺序存储结构是通过数组实现的,二集合的链接存储结构是通过存储节点之间的链接实现的,链接形成的结果称为链接表,通常使用单链表;当集合利用单链表存储时,集合中每个元素对应单链表中的一个结点,把这个元素存储到相应结点的值域中。由于集合中元素是无序的,所以在单链表中可以按任何次序链接。区别于数组结构,当向表示集合的单链表中插入一个元素结点时,为操作简单,把它插入到表头。即插入到 第一个节点之前使它成为新的表头节点,而原来的表头节点称为第2个结点,此时只改变新插入节点的指针域,使其指向原来的表头结点,在修改表头指针,使其指向新插入的节点,完成插入操作。当从链表中删除一个结点时,就是把该结点的指针域得值(即后一结点的地址)赋值给其前一个结点的指针域即可,若本身为表头节点,则应该把该结点的指针域的值赋值给表头指针。
//表示集合单链表的结构体
struct SNode{
ElemType date;//存储元素值的结点值域
SNode* nest;//为存储下一个结点地址的指针域
};
由于单链表中的结点通常是靠动态分配产生的,不需要事先分配存储空间,所以存储一个单链表只需要存储他的表头指针即可。有表头指针就能够访问该单链表。假定表头指针用HT表示,则HT应定义为
SNode* HT;//集合单链表的表头指针
HT----->[a1][-]--->[a2][-]--->...---->[ai][-]--->[a1+1][-]--->..--->[an][^]
1:初始化集合为空
void InitSet(SNode*& HT){
HT=NULL:
}
2:清除集合中所有元素并释放占有的动态存储空间:
void ClearSet(SNode*& HT){
SNode *p=HT,*q;//p指向HT单链表
while(p!=NULL){//回收HT集合中的每个结点
q=p->next;//q指向p的后继结点;
delete p;
p=q;
}
HT=NULL:
}
3:求出集合中元素个数:
int LenthSet(SNode* HT){
int n=0;
while(HT!=NULL){
n++;
HT=HT->next;
}
return n;
}
4:判断集合是否为空
bool EmptySet(SBode* HT){
return HT=NULL;
}
5:判断一个元素是否属于集合
bool InSet(SNode* HT,ElemType item){
while(HT!=NULL){
if(HT->date==item)return true;
else HT=HT->next;
}
return false;
}
6:输出集合中所有元素
void OutputSet(SNode* HT){
while(HT!=NULL){
cout<<HT->date<<" ";
HT=HT->next;
}
cout<<endl;
}
7:从集合中查找一个元素
bool FindSet(SNode* HT,ElemType& item){
while(HT!=NULL){
if(HT->date==item)break;
else HT=HT->next;
}
if(HT!=NUll){
item=HT->next;
return true;
}else return false;
}
8:修改集合中的一个指定元素
bool ModifySet(SNode* HT,const ElemType& item){
while(HT!=NULL){
if(Ht->date==item)break;
else HT=HT->next;
}
if(HT!=NULL){
HT->date=item;
return true;
}else return false;
}
9:向集合插入一个元素
bool InsertSet(SNode*& HT,ElemType item){
//建立值为item的新节点
SNode* tp=new SNode;
tp->date=item;
//从单链表中顺序查找是否存在值为item的结点
SNode* p=HT;
while(p!=NULL){
if(p->date==item)break;
else p=p->next;
}
//若不存在则把新节点插入到表头并返回真,否则不插入返回值。
if(p==NULL){
tp->next=HT;
HT=tp;
return true;
}else return false;
}
10:从集合中删除一个元素
bool DeleteSet(SNode*& HT,ElemType& item){
//从单链表中顺序查找是否存在值为item的结点
SNode *cp=HT,*ap=NULL;
while(cp!=NULL){
if(cp->date==item)break;
else {
ap=cp;
cp=cp->next;
}
}
//若不存在则返回假,表示删除失败
if(cp==NULL)return false;
//由item带回待测删除节点cp的完整值,若不需要带回可设item为值参
item=cp->date;
//从单链表中删除已找到的cp结点,对是否有表头应做不同处理;
if(ap==NULL)HT=cp->next;
else ap->next=cp->next;
delete cp;
return true;
}
11:求两个集合的并集
void UnionSet(SNode* HT1, SNode* HT2, SNode*& HT){
//置并集的表头指针HT为空
HT=NULL;
//把HT1集合单链表复制到HT集合单链表中
SNode* p=HT1;
while(p!=NULL){
SNode* newp=new SNode;
newp->date=p->date;
newp->next=p->next;
p=p->next;
}
//把HT2集合单链表中的每个元素插入到HT集合单链表中
p=HT2;
while(p!=NULL){
InsertSet(HT,p->date);
p=p->next;
}
}
12:求两个集合的交集
void InterseSet(SNode* HT1, SNode*HT2, SNode*& HT){
HT=NULL;
ElemType x;
SNode* p=HT2;
while(p!=NULL){
x=p->date;
bool b=FindSet(HT1,x);
if(b) InsertSet(HT,x);
p=p->next;
}
}
13:求两个集合的差集
void DifferenceSet(SNode* HT1, SNode* HT2, SNode*& HT){
HT=NULL;
ElemType x;
SNode* p=HT1;
while(p!=NULL){
x=p->date;
bool b=FindSet(HT2,x);
if(!b)InsertSet(HT,x);
p=p->next;
}
}
指针比较难理解一直不是太会,在上面的程序中有一个特殊的符号(*&)这个符号的含义是SNode * & HT ; 中SNode * 是个整体,表示变量类型是SNode类指针, &HT中的&表明引用实参,即代表实参的一个别名。SNode * &HT ; 中SNode * 是个整体,表示变量类型是SNode类指针, &HT中的&表明引用实参,即代表实参的一个别名。 操作引用变量就相当于操作实参变量;
慢慢理解,继续努力;