(三)双向链表的初始化、插入和删除

双向链表是在单链表的基础上增加了指向直接前驱的指针,所以在双向链表中的每一个节点都能很容易的找到他的前驱和后继。双向链表经常和循环链表一起使用,成为双向循环链表,他的尾指针的后继指向头结点,头结点的前驱指向尾节点,构成一个环的结果,这样,就算在尾节点也能很容易的找到头结点。

此处以双向链表为例

结构定义
typedef int  ElemType;
typedef struct DulNode{
    ElemType data;
    struct DulNode *prior;//直接前驱指针
    struct DulNode *next; //直接后继指针
}DulNode,*DuLinkList;
功能函数
//初始化
Status InitLink(DuLinkList *L){
    *L = (DuLinkList)malloc(sizeof(DulNode));
    if(!(*L))
        return ERROR;
    (*L)->prior = NULL;
    (*L)->next = NULL;
}

//尾插法
DuLinkList CreateLinkListT(DuLinkList L){
    ElemType n;
    DuLinkList p = L;
    printf("请输入要插入多少个元素:");
    scanf("%d",&n);
    for (int i = 1; i <= n; i++) {
        DuLinkList q = (DuLinkList)malloc(sizeof(DulNode));
        p->next = q;
        printf("请输入第%d个元素的值:",i);
        scanf("%d",&q->data);
        q->prior = p;
        q->next = NULL;
        p = q;
    }
    return L;
}

void OutputLinkList(DuLinkList L){
    DuLinkList p = L->next;
    int i = 1;
    while(p!=NULL){
        printf("第%d个元素的值是:%d,前驱是:%d\n",i,p->data,p->prior->data);
        p = p->next;
        i++;
    }
}

//双向链表第i个节点之间插入新的节点
DuLinkList InsertLinkList(DuLinkList L,int i,ElemType e){
    DuLinkList p,q;
    int j;
    p = L;
    //找到第i个节点前一个节点
    for(j=1;j<i;j++){
        p = p->next;
    }
    q = (DuLinkList)malloc(sizeof(DulNode));
    if(q){
        q->data = e;
        p->next->prior = q;
        q->next = p->next;
        p->next = q;
        q->prior = p;
    }
    return L;

}

//删除第i个节点
DuLinkList DeleteLinkList(DuLinkList L,int i){
    DuLinkList p,q;
    p = L->next;
    q = L;
    int j;
    //找到第i个节点p,和第i-1个节点q
    for(j=1;j<i;j++){
        p = p->next;
        q = q->next;
    }
    p->next->prior = q;
    q->next = p->next;
    free(p);
    return L;
}

main函数
int main() {

    DuLinkList L;
    InitLink(&L);
    CreateLinkListT(L);
    OutputLinkList(L);

    int i;
    ElemType e;
    printf("请输入要在第几个元素之前插入新节点:");
    scanf("%d",&i);
    printf("请输入要插入的数值:");
    scanf("%d",&e);
    InsertLinkList(L,i,e);
    OutputLinkList(L);

    printf("请输入要删除第几个节点:");
    scanf("%d",&i);
    DeleteLinkList(L,i);
    OutputLinkList(L);
    return 0;
}




双向链表是一种数据结构,每个节点有两个指针,分别指向前一个节点和后一个节点。它相比于单向链表可以双向遍历,插入删除操作可以更加方便地实现。 定义: ```C++ struct ListNode{ int val; ListNode *prev; ListNode *next; ListNode(int x): val(x), prev(nullptr), next(nullptr){} }; ``` 初始化: ```C++ ListNode *head = nullptr; ListNode *tail = nullptr; ``` 插入: - 在链表头部插入节点 ```C++ if(head == nullptr){ head = new ListNode(val); tail = head; } else { ListNode *new_node = new ListNode(val); new_node->next = head; head->prev = new_node; head = new_node; } ``` - 在链表尾部插入节点 ```C++ if(head == nullptr){ head = new ListNode(val); tail = head; } else { ListNode *new_node = new ListNode(val); tail->next = new_node; new_node->prev = tail; tail = new_node; } ``` - 在指定位置插入节点 ```C++ ListNode *new_node = new ListNode(val); ListNode *cur = head; while(cur != nullptr && cur->val != insert_val){ cur = cur->next; } if(cur == nullptr){ // 没有找到对应的节点,插入失败 delete new_node; } else { new_node->prev = cur->prev; new_node->next = cur; cur->prev->next = new_node; cur->prev = new_node; } ``` 删除: - 删除链表头部节点 ```C++ if(head == nullptr) return; ListNode *temp = head; head = head->next; if(head == nullptr){ tail = nullptr; } else { head->prev = nullptr; } delete temp; ``` - 删除链表尾部节点 ```C++ if(tail == nullptr) return; ListNode *temp = tail; tail = tail->prev; if(tail == nullptr){ head = nullptr; } else { tail->next = nullptr; } delete temp; ``` - 删除指定节点 ```C++ ListNode *cur = head; while(cur != nullptr && cur->val != delete_val){ cur = cur->next; } if(cur == nullptr){ // 没有找到对应的节点,删除失败 } else { cur->prev->next = cur->next; if(cur->next != nullptr){ cur->next->prev = cur->prev; } else { tail = cur->prev; } delete cur; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值