C语言实现双向链表:插入和删除

抽象数据类型

typedef sturct DuLnode 
{
    int data;
    struct DuLnode* next, *prior;
}DuLnode, *DuLinklist;

带头结点的双向链表:头节点的prior域为空,尾节点的next域为空。
双向循环链表:头节点的前驱指针指向尾节点,尾节点的后继指针指向头节点。

双向链表的头插法创建

(带头节点)
1.插入第一个节点和后续插入节点的方式有所不同,插入第一个节点的时候不需要考虑后继节点,从第二个插入节点需要考虑到前驱指针和后继指针的操作。

//插入第一个节点时
if(L->next == NULL)
{
    L->next = newNode;//头节点的next域指向新插入的第一个节点
    newNode->prior = L;//新插入的第一个节点的前驱指针指向头节点
    newNode->next = NULL;//将新插入的第一个节点的next赋空
}
//从插入第二个节点开始
newNode->next = L->next;//将上一个插入的节点连接到新插入的节点的next域
L->next->prior = newNode;//将上一个插入的节点的prior域指向新插入的节点
newNode->prior = L;//新插入节点的prior域指向头节点
L->next = newNode;//头节点的next域指向新插入的节点
//注意:要注意改变指针指向的顺序,不能先改变指向上一个节点(L->next)的指针指向,否则会找不到上一个节点的地址

双向链表的插入

C语言实现双向链表:插入和删除_第1张图片

s->prior = p->prior;//将要插入的节点的前驱指针指向前继节点
p->prior->next = s;//把前继节点的next域指向要插入节点
s->next = p;//要插入节点的后继指针指向后继节点(p指向的节点)
p->prior = s;//已知的p指向的节点的前驱指针指向要插入的节点(s指向的节点)

双向链表的删除

C语言实现双向链表:插入和删除_第2张图片

temp->prior->next = temp->next;//该删除节点的前驱节点的next域连接到该删除节点的后继节点
temp->next->prior = temp->prior;//该删除节点的后继节点的prior域连接到该删除节点的前驱节点
free(temp);

整体代码实现

#include 
#include 

typedef struct DuLnode
{
    int data;
    struct DuLnode *next, *prior;
}DuLnode, *DuLLinklist;

DuLLinklist CreateDuLlist(DuLLinklist L, int n)
{
    //创建头节点
    L->next = NULL;
    L->prior = NULL;
    //头插法创建双向链表
    //头插法,插入的第一个节点和后续要插入的节点的方式有所不同
    //插入第一个节点不需要考虑后继节点
    //第二个节点开始要考虑后继节点的前驱指针
    for(int i = 0; i < n; i++)
    {
        DuLLinklist newNode = (DuLLinklist)malloc(sizeof(DuLnode));
        printf("请输入要插入的节点值:");
        scanf("%d", &newNode->data);
        if(L->next == NULL)//插入第一个节点时
        {
            L->next = newNode;//头节点的next域指向新插入的节点
            newNode->prior = L;//新插入节点的prior域指向头节点
            newNode->next = NULL;//新插入节点的next赋空
        }
        else//插入后续节点
        {
            newNode->next = L->next;//将上一个插入的节点连接到新插入的节点的next域
            L->next->prior = newNode;//将上一个插入的节点的前驱prior域指向新插入的节点
            newNode->prior = L;//新插入节点的前驱域指向头节点
            L->next = newNode;//头节点的next域指向新插入的节点
        }
    }
}

void Printlist(DuLLinklist L, int n)
{
    DuLLinklist temp = L->next;
    printf("链表为:");
    for(int i = 0; i < n; i++)
    {
        printf("%d ", temp->data);
        temp = temp->next;
    }
}

DuLLinklist Listdelete(DuLLinklist L, int i)
{
    //DuLLinklist s = (DuLLinklist)malloc(sizeof(DuLnode));
    DuLLinklist temp = (DuLLinklist)malloc(sizeof(DuLnode));
    temp = L->next;
    int cnt = 1;
    while(cnt != i)//找到第i个要删除的节点
    {
        temp = temp->next;
        cnt++;
    }
    if(temp->next != NULL)
    {
        int e = temp->data;//保留要删除节点的数据
        temp->prior->next = temp->next;//该删除节点的前驱节点的next域连接到该删除节点的后继节点
        temp->next->prior = temp->prior;//该删除节点的后继节点的prior域连接到该删除节点的前驱节点
        free(temp);
    }
    else//如果删除的是最后一个节点
    {
        temp->prior->next = NULL;
        free(temp);
    }
}
int main()
{
    DuLLinklist L = (DuLLinklist)malloc(sizeof(DuLnode));
    int n, i;
    printf("请输入要创建多少个节点:");
    scanf("%d", &n);
    CreateDuLlist(L, n);
    printf("链表为:");
    Printlist(L, n);
    printf("输入要删除的节点:");
    scanf("%d", &i);
    Listdelete(L, i);
    Printlist(L, n);
    return 0;
}

你可能感兴趣的:(链表,c语言,数据结构)