需求:两个有序集做并集,但是有序集有两种,一种是基于数组的有序集,一个是基于链表的有序集。
希望通过多态,可以让ArraySet和ArraySet求并集,ListSet和ListSet求并集,ListSet和ArraySet求并集。
分析:不管是基于数组的还是链表的有序集,都是可以一样的操作, 两个游标指针,在两个集合上遍历,基本就是如下的格式。
void getUnion(Set *set1, Set *set2)
{
pos1 = set1.begin();
pos2 = set2.begin();
while (pos1 != set1.end() && pos2 != set2.end())
{
if (set1.current_value < set2.current_value)
{
this->insertElement(set1.current_value);
set1.next();
this->size++;
}
else if (...)
else ...
}
while (pos1 != set1.end())
{
...
}
while (pos2 != set2.end())
{
...
}
}
关键就是基于数组和基于链表在set1.insertElement(int k),set1.begin(), set1.end(), set1.next() set1.current_value()等方法的实现方法不用。所以就设置一个Set抽象类,设置这些函数的纯虚函数, 交由他的基类ArraySet,ListSet去实现。然后抽象类中自己实现getUnion函数,调用这些基础函数,来实现求并集的操作,但是这些基础函数具体怎么实现,Set类不用去管。
所以这样C++的实现就很简单。
/*
*Set抽象类
*/
class SET
{
public:
SET(){cardinal = 0}
virtual ~SET(){}
int Cardinal() const //集合元素个数
{
return cardinal;
}
bool isEmpty() const
{
return cardinal == 0;
}
bool isExist(double k) const //数据是否在集合中存在
{
bool flag = false;
for (MoveToBegin(); !Eos() && !flag; MoveToNext())
{
if (Get() == k)
{
flag = true;
}
}
return flag;
}
bool Append(double k) //添加
{
bool flag = false;
if (!isExist(k))
{
Insert(k);
cardinal++;
flag = true;
}
return flag;
}
bool Remove(double k) //删除
{
bool flag = false;
if (isExist(k))
{
Erease(k);
flag = true;
cardinal--;
}
return flag;
}
void Union(const SET *x, const SET *y) //求并集
{
Clear();
x->MoveToBegin();
y->MoveToBegin();
while (!x->Eos() && !y->Eos())
{
if (x->Get() < y->Get())
{
Append(x->Get());
x->MoveToNext();
}
else if (x->Get() > y->Get())
{
Append(y->Get());
y->MoveToNext();
}
else
{
Append(x->Get());
x->MoveToNext();
y->MoveToNext();
}
}
while (!x->Eos())
{
Append(x->Get());
x->MoveToNext();
}
while (!y->Eos())
{
Append(y->Get());
y->MoveToNext();
}
}
void Output() const //输出
{
for (MoveToBegin(); !Eos(); MoveToNext())
{
cout << Get() << " ";
}
putchar(10);
}
protected:
mutable void *p; //游标指针
private:
int cardinal;
virtual void MoveToBegin() const = 0; //这些纯虚函数有子类实现
virtual void MoveToEnd() const = 0;
virtual void MoveToPrev() const = 0;
virtual void MoveToNext() const = 0;
virtual bool Bos() const = 0;
virtual bool Eos() const = 0;
virtual double Get() const = 0;
virtual bool Set(double k) = 0;
virtual bool Insert(double k) = 0;
virtual bool Erease(double k) = 0;
virtual void Clear() = 0;
};
/*
*ASet派生类,要具体实现Set基类的纯虚函数
*/
class ASET : public SET
{
public:
ASET()
{
ele = new double[10];
size = 10;
length = 0;
//cout << "ASET CONSTRUCTED" << endl;
}
ASET(const ASET &x)
{
ele = new double[x.size];
for (int i = 0; i < x.length; i++)
{
ele[i] = x.ele[i];
}
//cout << "ASET COPY CONSTRUCTED" << endl;
}
virtual ~ASET()
{
delete [] ele;
size = 0;
length = 0;
//cout << "ASET DESTRUCTED" << endl;
}
ASET& operator = (const ASET &x)
{
if (this != &x)
{
delete [] ele;
ele = new double[x.size];
for (int i = 0; i < x.length; i++)
{
ele[i] = x.ele[i];
}
length = x.length;
size = x.size;
}
return *this;
}
private:
double *ele;
int size;
int length;
virtual void MoveToBegin() const
{
p = ele;
}
virtual void MoveToEnd() const
{
p = (ele + length);
}
virtual void MoveToPrev() const
{
p = ((double*)p - 1);
}
virtual void MoveToNext() const
{
p = ((double*)p + 1);
}
virtual bool Bos() const
{
return p == ele;
}
virtual bool Eos() const
{
return p == ele + length;
}
virtual double Get() const
{
return *((double*)p);
}
virtual bool Set(double k)
{
bool flag = false;
if (p >= ele && !Eos())
{
double *temp = (double*)p;
*temp = k;
flag = true;
}
return flag;
}
virtual bool Insert(double k)
{
if (length == size)
{
Resize(2 * size);
}
int i = length - 1;
while (i >= 0)
{
if (ele[i] > k)
{
ele[i + 1] = ele[i];
}
else
{
break;
}
i--;
}
ele[i + 1] = k;
length++;
return true;
}
virtual bool Erease(double k)
{
bool flag = false;
for (int i = 0; i < length; i++)
{
if (!flag && ele[i] == k)
{
flag = true;
}
if (flag && i < length - 1)
{
ele[i] = ele[i + 1];
}
}
length -= flag;
return flag;
}
virtual void Clear()
{
length = 0;
}
void Resize(int newsize)
{
double *temp = new double[newsize];
for (int i = 0; i < length; i++)
{
temp[i] = ele[i];
}
delete [] ele;
ele = temp;
size = newsize;
}
};
/*
*同理LSet类
*/
struct LNODE
{
double k;
LNODE *next;
LNODE(double k, LNODE *next) : k(k), next(next){}
};
class LSET : public SET
{
public:
LSET()
{
head = new LNODE(0, NULL);
length = 0;
//cout << "LSET CONSTRUCTED" << endl;
}
~LSET()
{
Clear();
delete head;
length = 0;
//cout << "LSET DESTRUCTED" << endl;
}
LSET(const LSET &x)
{
*this = x;
//cout << "ASET COPY CONSTRUCTED" << endl;
}
LSET& operator = (const LSET &x)
{
if (&x != this)
{
Clear();
LNODE *p = x.head->next;
LNODE *q = this->head;
while (p)
{
LNODE *temp = new LNODE(p->k, NULL);
q->next = temp;
q = q->next;
p = p->next;
}
length = x.length;
}
return *this;
}
private:
LNODE *head;
int length;
virtual void MoveToBegin() const
{
p = head->next;
}
virtual void MoveToEnd() const
{
p = NULL;
}
virtual void MoveToPrev() const
{
LNODE *q = head->next;
if (p != head->next)
{
for (q = head->next; q != NULL && q->next != p; q = q->next);
}
p = q;
}
virtual void MoveToNext() const
{
if (p != NULL)
{
p = reinterpret_cast<void*>(reinterpret_cast<LNODE*>(p)->next);
}
}
virtual bool Bos() const
{
return p == head->next;
}
virtual bool Eos() const
{
return p == NULL;
}
virtual double Get() const
{
return reinterpret_cast<LNODE*>(p)->k;
}
virtual bool Set(double k)
{
int flag = false;
if (p)
{
reinterpret_cast<LNODE*>(p)->k = k;
}
return flag;
}
virtual bool Insert(double k)
{
LNODE *p = head;
bool flag = false;
while (p->next)
{
if (p->next->k == k)
{
break;
}
else if (p->next->k < k)
{
p = p->next;
}
else
{
p->next = new LNODE(k, p->next);
flag = true;
}
}
if (p->next == NULL)
{
p->next = new LNODE(k, p->next);
flag = true;
}
length += flag;
return flag;
}
virtual bool Erease(double k)
{
bool flag = false;
LNODE *p = head;
while (p->next)
{
if(p->next->k == k)
{
LNODE *temp = p->next;
p = temp->next;
delete temp;
flag = true;
}
}
length -= flag;
return flag;
}
virtual void Clear()
{
while (head->next)
{
LNODE *p = head->next;
head->next = p->next;
delete p;
}
length = 0;
}
};
int main()
{
SET *x = new ASET();
SET *y = new LSET();
SET *z = new ASET();
for (int i = 0; i < 5; i++)
{
x->Append(1.0 * i);
}
for (int j = 0; j < 3; j++)
{
y->Append(2.0 * j + 1);
}
z->Union(x, y);
x->Output();
y->Output();
z->Output();
delete x;
delete y;
return 0;
}
在Object-C中可以用协议实现类似的方法。但是要求实现基类的程序员会实现GetUnion方法,这是一个缺点,因为实际问题中可能GetUnion方法很复杂。简单实现如下:
/*
*协议部分
*/
@protocol SetProtocal <NSObject>
- (void) nextElemen;
- (void) prevElemen;
- (void) insertElement:(int)ele;
- (void) ereaseElement:(int)ele;
- (int) getSize;
- (int) getValue;
- (void)toBegin;
- (bool)isEnd;
- (void) getUnionWith:(id<SetProtocal>) x andWith:(id<SetProtocal>)y;
- (void) Output;
- (void)clear;
@end
//-------------------------------------------------------------------------------
/*
*ArraySet
*/
@interface ArraySet : NSObject<SetProtocal>
{
@private
int *_ele, *_pos;
}
@property(nonatomic, assign, readonly)int size;
- (instancetype)initWith:(int)capacity;
@end
//-------------------------------------------------------------------------------
typedef struct node
{
int data;
struct node *next;
}node;
@interface ListSet : NSObject<SetProtocal>
{
@private
node *_head, *_pos;
int _size;
}
- (instancetype)init;
@end
//-------------------------------------------------------------------------------
//具体类的.m文件自己实现吧。
//main
int main()
{
id<SetProtocal> s1 = [[ListSet alloc] init];
id<SetProtocal> s2 = [[ArraySet alloc] initWith:10];
id<SetProtocal> s3 = [[ArraySet alloc] initWith:10];
[s1 insertElement:3];
[s1 insertElement:2];
[s1 insertElement:4];
[s1 Output];
[s2 insertElement:1];
[s2 insertElement:2];
[s2 insertElement:3];
[s2 Output];
[s3 getUnionWith:s1 andWith:s2];
[s3 Output];
return 0;
}
在OC类中,由于所有函数都是虚函数,并且也可以不实现,所以也可以直接用类的特性,来实现多态。
在这个例子中,用StringNumber和汉字数字相加。”123“ + ”一二三“ = 246;
@interface Number : NSObject
-(int)toStandardInteger;
-(int)SumWith:(Number*)num1 andWith:(Number*)num2;
@property(nonatomic, strong)NSString *num;
@end
-(int)SumWith:(Number*)num1 andWith:(Number*)num2
{
return [num1 toStandardInteger] + [num2 toStandardInteger];
}
//--------——--------——--------——--------——--------——--------——--------——
@interface StringNumber : Number
-(int)toStandardInteger;
@end
@implementation StringNumber
-(int)toStandardInteger
{
unsigned long len = [self.num length];
int res = 0;
for (int i = 0; i < len; i++)
{
res = res * 10 + [self.num characterAtIndex:i] - '0';
}
return res;
}
@end
//--------——--------——--------——--------——--------——--------——--------——
@interface ChineseNumber : Number
{
@private
int _map[65536];
}
@end
@implementation ChineseNumber
- (instancetype)init
{
self = [super init];
NSString *nums = @"一二三四五六";
_map[[nums characterAtIndex:0]] = 1;
_map[[nums characterAtIndex:1]] = 2;
_map[[nums characterAtIndex:2]] = 3;
_map[[nums characterAtIndex:3]] = 4;
_map[[nums characterAtIndex:4]] = 5;
_map[[nums characterAtIndex:5]] = 6;
return self;
}
-(int)toStandardInteger
{
int len = [self.num length], res = 0;
for (int i = 0; i < len; i++)
{
res = res * 10 + _map[[self.num characterAtIndex:i]];
}
return res;
}
@end
//---------------------------------------------------------------------------
#import <Foundation/Foundation.h>
#import "Number.h"
#import "StringNumber.h"
#import "ChineseNumber.h"
int main(int argc, const char * argv[])
{
Number *num1 = [StringNumber new];
Number *num2 = [ChineseNumber new];
Number *num3 = [StringNumber new];
num1.num = @"123";
num2.num = @"一二三";
int res = [num3 SumWith:num1 andWith:num2];
NSLog(@"%d", res);
return 0;
}