链表中可以存不同类型的值,比如可以存int、 char、float等类型。很明显,这道编程题的意图在于C++的虚函数使用和多态性的实现。虽然,多态似乎是面向对象语言的专利,但是其实,C语言同样可以实现多态性。
这里用到的利器就是void指针。我们可以在节点的结构体中声明一个void指针,再声明一个类型标记,表示这个void指针指向的类型。链表节点的结构体声明如下:
enum data_type
{
INT,
FLOAT,
CHAR,
STRING
};
struct node
{
void *data;
int type;
struct node* next;
};
typedef struct node* plist;
这里的枚举了程序所支持的类型,目前支持int,char,float和字符串类型,当然这个可以根据需要,自己定义了。
插入函数如下:
static plist new_node(void *data, int type)
{
plist p = (plist)malloc(sizeof(struct node));
p->data = data;
p->type = type;
p->next = NULL;
return p;
}
void add2head(plist head, void *data, int type)
{
plist p = new_node(data, type);
p->next = head->next;
head->next = p;
}
插入的时候需要指明变量的类型,即type的值。
删除函数:
static int x_cmp(plist p, void *data, int type)
{
int ret = -1;
switch(type)
{
case INT:
ret = memcmp(p->data, data, sizeof(int));break;
case FLOAT:
ret = memcmp(p->data, data, sizeof(float));break;
case CHAR:
ret = memcmp(p->data, data, sizeof(char));break;
case STRING:
ret = memcmp(p->data, data, strlen(data));break;
}
return ret;
}
static int x_del_node(plist head, void *data, int type, int (*cmp)(plist, void *, int))
{
plist p = head->next, pre = head;
while(p)
{
if(0 == cmp(p, data, type))
{
pre->next = p->next;
free(p);
return 1;
}
pre = p;
p = p->next;
}
return 0;
}
int del_node(plist head, void *data, int type)
{
return x_del_node(head, data, type, &x_cmp);
}
这里的难点就在于用到了函数指针,将函数指针作为参数传递给调用函数x_del_node中。利用函数指针,我们只需根据不同的情况适当修改x_cmp函数的内容即可