链表——双链表

头文件 MyList.h

#ifndef _MYLIST_H_
#define _MYLIST_H_

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

struct Node;
typedef struct Node *pNode;

struct Head;
typedef struct Head *pHead;

pHead Create (void);                            // 初始化头节点
int GetLength (pHead pH);                       // 获得链表长度
bool IsEmpty (pHead pH);                        // 判断链表是否为空
void Insert (pHead pH, int pos, int val);       // 插入元素
pNode Delete (pHead pH, int val);               // 删除链表中的元素
pNode Search (pHead pH, int val);               // 查找元素
void Destory (pHead pH);                        // 销毁链表
void PrintFront (pHead pH);                     // 顺序打印链表
void PrintReverse (pHead pH);                   // 逆序打印链表

struct Head
{
    int length;         // 记录链表长度

    pNode next;
};

struct Node
{
    int data;

    pNode pre;          // 指向前一个节点,前驱指针
    pNode next;         // 只想后一个节点,后继指针
};



pHead
Create (void)
{
    pHead pH = (pHead)malloc (sizeof (struct Head));

    if (pH == NULL)
    {
        printf ("Error Create!");

        exit (1);
    }

    pH -> length = 0;
    pH -> next = NULL;

    return pH;
}

int
GetLengh (pHead pH)
{
    if (pH == NULL)
    {
        printf ("Error Head!");

        exit (1);
    }

    return pH -> length;
}

bool
IsEmpty (pHead pH)
{
    if (pH == NULL)
    {
        printf ("Error Head!");

        exit (1);
    }

    if (pH -> length == 0)
    {
        return true;
    }

    return false;
}

void
Insert (pHead pH, int pos, int val)
{
    if (pH == NULL || pos < 0 || pos > pH -> length)
    {
        printf ("Error Input!");

        exit (1);
    }

    pNode p = (pNode)malloc (sizeof (struct Node));

    if (p == NULL)
    {
        printf ("Error Memory!");

        exit (1);
    }

    p -> data = val;        // 将 val 保存在新节点数据域中

    if (IsEmpty (pH))       // 链表为空
    {
        pH -> next = p;     // 将头节点与新节点链接

        p -> pre = NULL;
        p -> next = NULL;
    }
    else
    {
        pNode pCur = pH -> next;        // 头节点的下一个节点

        if (pos == 0)                   // 在头节点后插入
        {
            pH -> next = p;             // 将头节点与新节点链接

            p -> pre = NULL;
            p -> next = pCur;           // 将新节点与原头节点后的节点相连接
            pCur -> pre = p;            // 将原节点前驱指针指向新节点
        }
        else                                        // 不是第一个位置
        {
            for (int i = 1; i < pos; i ++)
            {
                pCur = pCur -> next;                // 遍历找到插入位置
            }
                                                    // 结束后pCur指向要插入位置的节点
            p -> next = pCur -> next;               // 将新节点与当前节点的下一节点链接
            pCur -> next -> pre = p;                // 将当前节点的下一节点前驱指针指向新节点
            p -> pre = pCur;                        // 将新节点的前驱指针指向当前节点
            pCur -> next = p;                       // 将当前节点与新节点链接
        }
    }

    pH -> length ++;                    // 长度加 1
}

pNode
Delete (pHead pH, int val)
{
    if (pH == NULL || pH -> length == 0)
    {
        printf ("Error Head!");

        exit (1);
    }

    pNode p = Search (pH, val);     // 通过 Search 函数找到该节点

    if (p == NULL)
    {
        printf ("Error input!");

        return NULL;
    }

    pNode pPre = p -> pre;
    pNode pNext = p -> next;
                                    // 将删除节点的前后节点相链接
    pNext -> pre = pPre;
    pPre -> next = pNext;

    printf ("成功删除!\n");

    return p;
}

pNode
Search (pHead pH, int val)
{
    if (pH == NULL)
    {
        printf ("Error Head!");
    }

    pNode p = pH -> next;

    do
    {
        if (p -> data == val)
        {
            return p;
        }

        p = p -> next;
    }
    while (p -> next != NULL);

    printf ("Not Found!\n");

    return NULL;
}

void
Destory (pHead pH)
{
    pNode pCur = pH -> next;
    pNode p = NULL;

    if (pH == NULL)
    {
        printf ("Error Head!");
    }

    while (pCur -> next != NULL)
    {
        p = pCur -> next;       // 通过 p 来传递节点地址

        free (pCur);            // 释放该节点

        pCur = p;
    }

    pH -> length = 0;           // 回到初始化
    pH -> next = NULL;
}

void
PrintFront (pHead pH)
{
    if (pH == NULL)
    {
        printf ("Error Head!");
    }

    pNode p = pH -> next;

    while (p != NULL)
    {
        printf ("%d ", p -> data);

        p = p -> next;
    }

    printf ("\n");
}

void
PrintReverse (pHead pH)
{
    if (pH == NULL)
    {
        printf ("Error Head!");
    }

    pNode p = pH ->next;

    while (p -> next != NULL)               // 先遍历至链表末尾
    {
        p = p -> next;
    }

    int len = pH -> length;

    for (int i = len - 1; i >= 0; i --)     // 从后向前打印
    {
        printf ("%d ", p -> data);

        p = p -> pre;
    }

    printf ("\n");
}

#endif // _MYLIST_H_

测试文件 main.c

#include "../../MyHeader/MyList.h"

/**@Author Ivan Lee **/

int main(void)
{
    pHead pH = NULL;
    pH = Create ();                // 创建双链表

    int num;
    printf ("请输入要插入的元素, 输入-1结束 \n");

    while (1)
    {
        scanf ("%d", &num);

        if (num == -1)
        {
            break;
        }

        Insert (pH, 0, num);
    }

    printf ("当前双链表长度: %d \n", GetLengh (pH));

    printf ("顺序打印链表: \n");
    PrintFront (pH);

    printf ("逆序打印链表: \n");
    PrintReverse (pH);

    int target;
    printf ("请输入要查找的元素: ");
    scanf ("%d", &target);
    Search (pH, target);

    int del;
    printf ("请输入要删除的元素: ");
    scanf ("%d", &del);
    Delete (pH, del);
    printf ("删除后链表元素: \n");
    PrintFront (pH);

    Destory (pH);
    printf ("成功销毁!\n");

    printf ("当前链表长度为 %d \n", pH -> length);

    system ("pause");
    return 0;
}

PS 采用的头插法,因此非常义上的顺序逆序输出

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

神秘的企鹅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值