在“C语言指针(四)–链表”这篇文章中我讲解了单向链表,但是在链表的家族中我们还经常见到双向链表和双(单)向循环链表。我们可以从他们的名字想象出它们在内存中的样子。
我们根据上图定义双链表节点的数据结构实现插入、删除和遍历等操作:
typedef struct node
{
int data;
struct node *prev;
struct node *next;
}Node;
void insert(Node *node, int data)
{
Node *p = (Node *)malloc(sizeof(Node));
if(p != NULL)
{
p->data = data;
p->next = node->next;
p->prev = node;
node->next = p;
p->next->prev = p;
}
}
void remove(Node *node)
{
if(node != NULL)
{
node->prev->next = node->next;
node->next->prev = node->prev;
free(node);
}
}
Node* list_append(Node* head, int data)
{
Node *p;
Node *node = (Node *)malloc(sizeof (Node *));
if(head != NULL)
{
if(node != NULL)
{
node->data = data;
node->next = NULL;
p = head;
while (p->next !=NULL) {
p = p->next;
}
p->next = node;
node->prev = p;
}
}
else {
head = (Node *)malloc(sizeof (Node *));
if(head != NULL)
{
head->data = data;
head->next = NULL;
head->prev = NULL;
}
}
return head;
}
void list_ergodic(Node *head,
void *function(Node *p, void *),
void* prg)
{
Node *node = head;
while (node != NULL) {
function(node, prg);
node = node->next;
}
}
void func(Node *p, void *prg)
{
printf("%d\n", p->data);
}
int main()
{
int i;
Node *head = NULL;
Node *node = NULL;
node = head;
for (i= 0; i < 10; i++) {
head = list_append(head, i);
}
list_ergodic(head, func, NULL);
}
到此简单的双向链表就实现了,我在此只实现了链表的增、删、改和遍历。读者可以根据需要在自己的应用中实现其他特殊的操作,灵活的使用链表能够大大提高程序的效率。
我这个人比较懒,循环链表就是将单链表或者双向链表的首尾连接起来,读者可以在前面的基础上实现。我这里就不给出历程了。