数据结构与算法 --- 双向链表

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

typedef struct Node
{
    int data;
    struct Node *pNext;
    struct Node *pRior;
} NODE, *PNODE;

PNODE pHead;

PNODE init_link(int data);
bool crate_link(PNODE, int);
void traverse(PNODE);
bool insert_tail(PNODE pHead, PNODE pNew);
bool insert_head(PNODE pHead, PNODE pNew);
bool insert_position(PNODE pHead, PNODE pNew, int pos);
bool delete_node(PNODE pHead, int pos, int *data);

int main()
{
    //创建一个头节点,但是头节点不存放数据
    int data = 0;
    pHead = init_link(0);
    if (crate_link(pHead, 5))
    {
        printf("创建链表成功\n");
    }
    traverse(pHead);

    printf("=============insert 0 in tail=================\n");
    insert_tail(pHead, init_link(0));
    traverse(pHead);

    printf("=============insert 6 in head=================\n");
    insert_head(pHead, init_link(6));
    traverse(pHead);

    printf("=============insert 7 in pos1=================\n");
    insert_position(pHead, init_link(7), 8);
    traverse(pHead);

    printf("=============delete an pos8=================\n");
    delete_node(pHead, 8, &data);
    traverse(pHead);
    printf("delete data is %d\n", data);

    return 0;
}
//初始化一个节点
PNODE init_link(int data)
{
    PNODE pNode = (PNODE)malloc(sizeof(NODE));
    if (NULL == pNode)
    {
        printf("动态分配内存失败\n");
        exit(-1);
    }
    pNode->pNext = NULL;
    pNode->pRior = NULL;
    pNode->data = data;
    return pNode;
}

//创建链表
bool crate_link(PNODE pHead, int len)
{
    if (NULL == pHead)
        return false;

    PNODE list = pHead;
    do
    {
        PNODE pNew = (PNODE)malloc(sizeof(NODE));
        if (NULL == pNew)
        {
            printf("动态分配内存失败\n");
            exit(-1);
        }
        pNew->data = len;
        pNew->pNext = NULL;
        pNew->pRior = NULL;

        list->pNext = pNew;
        pNew->pRior = list;
        list = list->pNext;
    } while (--len);

    return true;
}

//双向链表遍历
void traverse(PNODE pHead)
{
    if (NULL == pHead)
        return;
    PNODE p = pHead;
    while (NULL != p->pNext)
    {
        printf("%d ", p->pNext->data);
        p = p->pNext;
    }
    putchar('\n');
    while (p->pRior != NULL)
    {
        printf("%d ", p->data);
        p = p->pRior;
    }
    putchar('\n');
}

//在尾部插入一个节点
bool insert_tail(PNODE pHead, PNODE pNew)
{
    // 1. 判断链表是否存在
    if (NULL == pHead)
    {
        printf("请先初始化链表\n");
        return false;
    }

    // 2. 将p指向链表尾部
    PNODE p = pHead;
    while (NULL != p->pNext)
    {
        p = p->pNext;
    }

    // 3. 让新节点与最后一个节点进行双层逻辑关系;
    p->pNext = pNew;
    pNew->pRior = p;
    pNew->pNext = NULL;
    return true;
}

// 插入头节点前面
bool insert_head(PNODE pHead, PNODE pNew)
{
    // 1. 判断链表是否存在
    if (NULL == pHead)
    {
        printf("请先初始化链表\n");
        return false;
    }

    // 2. 判断头节点的下一个节点是否存在
    if (pHead->pNext == NULL)
    {
        pHead->pNext = pNew;
    }
    else
    {
        PNODE p = pHead;
        p->pNext->pRior = pNew;
        pNew->pNext = p->pNext;
        p->pNext = pNew;
        pNew->pRior = p;
    }

    return true;
}

int getlinklen()
{
    int len = 0;
    PNODE p = pHead->pNext;
    while (p != NULL)
    {
        len++;
        p = p->pNext;
    }
    return len;
}

bool insert_position(PNODE pHead, PNODE pNew, int pos)
{
    int len = 0;
    // 1. 判断链表是否存在
    if (NULL == pHead)
    {
        printf("请先初始化链表\n");
        return false;
    }
    // 2. 可以插入的位置,第一个节点到最后一个节点+1
    //    假设有5个节点。 那么可以插入的位置有 1 2 3 4 5 6

    len = getlinklen();
    printf("link length is %d\n", len);
    // 3. 如果pos位置为0 或者大于6那么将不能插入

    if (pos < 1 || pos > len + 1)
    {
        return false;
    }
    else
    {
        PNODE p = pHead;
        // 将p定位到pos位置
        // 两种情况
        // 1、pos = len+1; 这时候遍历整个link 肯定是溢出了,所以得 && 上 p->pNext != NULL 这个条件,不然会出现段错误
        // 2、pos < len+1; 这时候就可以遍历整个link 找到pos位置进行插入一个节点
        while (p->pNext != NULL && pos--)
        {
            p = p->pNext;
        }
        //如果是插入的位置是最后一个节点+1 的位置
        if (p->pNext == NULL && pos == 1) //pos==1 说明插入节点是最后一个节点的后一个节点
        {
            p->pNext = pNew;
            pNew->pRior = p;
        }
        else
        {
            p->pRior->pNext = pNew;
            pNew->pNext = p;
            pNew->pRior = p->pRior;
            p->pRior = pNew;
        }
    }
    return true;
}

bool delete_node(PNODE pHead, int pos, int *data)
{
    int len = 0;
    // 1. 判断链表是否存在
    if (NULL == pHead)
    {
        printf("请先初始化链表\n");
        return false;
    }

    len = getlinklen();
    printf("link length is %d\n", len);

    // 2. 判断删除的节点位置是否在范围之内
    if (pos < 1 || pos > len)
    {
        return false;
    }
    else
    {
        PNODE p = pHead;
        while (pos--)
        {
            p = p->pNext;
        }

        if (p->pNext == NULL) //如果是最后一个节点
        {
            *data = p->data;
            p->pRior->pNext = NULL; //注意要让上一个节点pNext 指向NULL
            free(p);
            p->pRior = NULL; //释放完节点后,将节点的前指针域指向NULL,不然它将成为迷途指针
        }
        else
        { //如果是中间节点
            *data = p->data;
            p->pRior->pNext = p->pNext;
            p->pNext->pRior = p->pRior;
            free(p);
            p->pNext = NULL;
            p->pRior = NULL;
        }
        return true;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值