易百教程

双向链表

双向链表将允许在任一方向上查看列表。

除了指向下一个结构的指针之外,还可以在每个结构中包含一个额外的指针来存储上一个结构体的地址。

示例代码

#define __STDC_WANT_LIB_EXT1__ 1
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>

typedef struct Dog Dog;       // 定义类型名称为:Dog

struct Dog                    // 结构体类型定义
{
    int age;// 年龄
    int height; // 高度
    char name[20];
    char father[20];
    char mother[20];
    Dog *next;                    // 指定下一个结构体
    Dog *previous;                // 指定上一个结构体
};

int main(void)
{
    Dog *first = NULL;            // 指向第一个 dog
    Dog *current = NULL;          // 指向当前 dog
    Dog *last = NULL;             // 指向最后一个 dog

    char test = '\0';               // 标志结束字符

    while ( 1 )
    {
        printf_s("Do you want to enter details of a%s dog (Y or N)? ",
            first != NULL ? "nother" : "");
        scanf_s(" %c", &test, sizeof(test));
        if (tolower(test) == 'n')
            break;

        // 为每个新的 Dog 结构体分配内存
        current = (Dog*)malloc(sizeof(Dog));
        if (first == NULL)
        {
            first = current;            // 设置指向第一只狗的指针
            current->previous = NULL;
        }
        else
        {
            last->next = current;       // 设置前一只狗的下一个地址
            current->previous = last;   // Previous address for current dog
        }
        printf_s("Enter the name of the dog: ");
        scanf_s("%s", current->name, sizeof(current->name));

        printf_s("How old is %s? ", current->name);
        scanf_s("%d", &current->age);

        printf_s("How high is %s ( in hands )? ", current->name);
        scanf_s("%d", &current->height);

        printf_s("Who is %s's father? ", current->name);
        scanf_s("%s", current->father, sizeof(current->father));

        printf_s("Who is %s's mother? ", current->name);
        scanf_s("%s", current->mother, sizeof(current->mother));

        current->next = NULL;         // In case it's the last...
        last = current;               // ...save its address
    }

    // 打印数据
    printf_s("\n");
    while (current != NULL)          // 以相反的顺序输出狗的数据
    {
        printf_s("%s is %d years old, %d hands high,",
            current->name, current->age, current->height);
        printf_s(" and has %s and %s as parents.\n", current->father,
            current->mother);
        last = current;               // 保存指针以释放要释放的内存
        current = current->previous;  // 当前指向链表中的上一个
        free(last);                   // 释放内存
        last = NULL;
    }
    first = NULL;

    system("pause");
    return 0;
}

执行上面示例代码,得到以下结果:

Do you want to enter details of a dog (Y or N)? Y
Enter the name of the dog: Hei
How old is Hei? 2
How high is Hei ( in hands )? 2
Who is Hei's father? FHei
Who is Hei's mother? MHei
Do you want to enter details of another dog (Y or N)? n

Hei is 2 years old, 2 hands high, and has FHei and MHei as parents.

Dog结构体的定义为:

struct Dog                      // 结构体类型定义
{
  ...
  Dog *next;                    // 指向下一个结构体的指针
  Dog *previous;                // 指向上一个结构体的指针
};

Dog结构体包含两个指针:一个指向列表中的前向,称为next,另一个指向前一个结构体,称为previous

这允许列表在两个方向(向前和向后)上遍历结构体元素。