C语言实现的双链表创建 、插入、删除、指定位置翻转操作的操作

以下代码都是经验证可执行,具体结果可参考 dl_print 打印信息。
代码里面对过程进行了注释便于理解

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

//定义双向链表的节点结构
typedef struct Node{

    int value;
    struct Node *next;
    struct Node *prev;
}Double_Node;

//创建双向链表
Double_Node* creat_dblist(int value)
{
    Double_Node* head = NULL;
    head = (Double_Node*) malloc(sizeof(Double_Node));
    if(head == NULL)
        printf("creat double list head failed ! \n");
    else
    {
        head->value = value;
        head->prev = NULL;
        head->next = NULL;//链表的节点是NULL
    }
    return head;
}
//创建长度为length(算上链表头)的双向链表,value为元素数组 , length为创建双链表长度
Double_Node* creat_length_dblist(int* value ,int length)
{
    Double_Node* dl_head = NULL;//创建个链表头
    Double_Node *dl_new = NULL;
    Double_Node *dl_temp = NULL;
    int i ;
    dl_head = (Double_Node*)malloc(sizeof(Double_Node));
    if(dl_head == NULL)
        printf("creat double list head failed ! \n");
    else
    {
        dl_head->value = value[0];
        dl_head->prev = NULL;
        dl_head->next = NULL;
        dl_temp = dl_head;//创建第一个节点,头尾相同
        for(i=1;i<length;i++)
        {
            dl_new = (Double_Node*)malloc(sizeof(Double_Node));
            if(dl_new == NULL)
                printf("creat double list head failed ! \n");
            else
            {
                //第一次新增的 dl_new_1 的 prev 是 head节点,即 dl_temp,新增节点位于尾部 ,故 next 是NULL
                //第二次新增的 dl_new_2 的 prev 是 第一次新增的节点,即 dl_temp( dl_new_1),新增节点位于尾部 next 是NULL
                //后面类推。。。
                dl_new->value = value[i];
                dl_new->prev = dl_temp;
                dl_new->next = NULL;
                //第一次 dl_temp(dl_new_1) 是头节点,next 指向新增的节点即 dl_new
                //第二次 dl_temp(dl_new_2) 是新增的第一个节点,prev节点操作已经执行(dl_new->prev = dl_temp;),此时next 指向新增的 dl_new_2。
                //后面类推。。。
                dl_temp->next = dl_new;

                //进行下一次做准备
                dl_temp = dl_new;
            }
        }
    }
    return dl_head;

}

//打印链表中的元素 ,传入的是链表头结点
void dl_print(Double_Node* head)
{
    while(head)
    {
        printf("---%d---",head->value);
        head = head->next;
    }
    printf("\n");

}

//双向链表的插入元素操作:后向插入
/*
 * 有两种方式:1.传入二级指针,这样可以改变指针本身  2.返回的对象是指针
 */
//传入的参数是链表的头节点以及需要插入的元素
Double_Node* insert_node(Double_Node* head ,int value)
{
    Double_Node* temp = head;
    Double_Node* new  = NULL;
    new = (Double_Node*)malloc(sizeof(Double_Node));
    new->value = value;

    while(temp)
    {
        if(temp->value > value && temp->next)
        {
            //可能存在头部 中间
            //1.插入在头部
            if(temp->prev == NULL)
            {
                new->prev = NULL;
                new->next = temp;
                temp->prev = new; 
                head = new;
                break;
            }
            //2.插入在中间 new tmp
            if(temp->next)
            {
                new->prev = temp->prev;
                new->next = temp;
                temp->prev->next = new;
                temp->prev = new;
                break;
            }
        }
        //插在尾部
        if(temp->next == NULL)
        {           
            temp->next = new;
            new->prev = temp;
            new->next = NULL;
            break;
        }
        temp = temp->next;

    }

    return head;
}

//双向链表的删除节点
Double_Node* del_node(Double_Node* head ,int value)
{
    Double_Node* temp = head;
    while(temp)
    {
        if(temp->value == value)
        {
            //1.删除头节点
            if(temp->prev == NULL)
            {
                head->next->prev = NULL;
                head = head->next;
                free(temp);
                break;
            }
            //2.删除尾节点
            else if(temp->next ==NULL)
            {
                temp->prev->next = NULL;
                free(temp);
                break;
            }
            //3.删除中间节点
            else
            {
                temp->prev->next = temp->next;
                temp->next->prev = temp->prev;
                free(temp);
                break;
            }
        }
        temp = temp->next;
    }
    return head;
}
//根据指定的位置进行转换链表,如A->B->C->D->E->F  以 C 点 为转换 C->D->E->F->A->B
Double_Node* change_dblist(Double_Node* head ,int value)
{
    Double_Node* temp;
    Double_Node* tail;
    temp = head;
    tail = head;
    //找到尾节点
    while(tail)
    {
        if(tail->next==NULL)//尾节点
            break;
        tail = tail->next;
    }
    while(temp)
    {
        if(temp->value == value)//说明节点存在
        {
            //1.翻转节点为头节点
            //A->B->C->D->E->F 不变
            if(temp->prev == NULL)
            {
                //无需操作
                break;

            }
            //2.翻转节点为尾节点
            //F->A->B->C->D->E
            else if(temp->next == NULL)
            {
                temp->prev->next = NULL;//变成尾节点
                head->prev = temp;
                temp->next = head;
                temp->prev = NULL;
                head = temp;
                break;

            }
            //3.翻转节点为中间位置
            //C->D->E->F->A->B
            else
            {
                temp->prev->next = NULL;//变成尾节点
                //找到尾节点
                tail->next = head;
                head->prev = tail;
                head = temp;
                break;

            }
        }
        temp = temp->next;
    }
    return head;
}
int main()
{
    Double_Node* head = NULL;
    int length = 10;
    int value[10] = {1,3,5,7,9,11,13,15,17,19};
    head = creat_length_dblist(value,length);
    if(head == NULL)
        printf(" creat double list head failed !\n");
    else
    {
        printf(" creat double list head successed !\n");
        dl_print(head);
        head = insert_node(head,0);
        dl_print(head);
        head = insert_node(head,4);
        dl_print(head);
        head = insert_node(head,30);
        dl_print(head);
        head = del_node(head,0);
        dl_print(head);
        head = del_node(head,4);
        dl_print(head);
        head = del_node(head,30);
        dl_print(head);
        head = change_dblist(head,19);
        dl_print(head);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值