zoukankan      html  css  js  c++  java
  • 双向循环链表

    双向循环链表

     双向循环链表和单向循环链表一样都是线性链式存储结构,顾名思义双向循环链表就是在两个方向都可以访问任一数据。

    头节点设计

     调用下面代码创建一个结点作为头结点,让它的头指针prev和尾指针next都指向自己,最后返回这个头结点的堆地址。

    p_douoble_crclist new_node()
    {
        p_douoble_crclist new = calloc(1, sizeof(my_double_crclist));
    
        if(NULL == new)
        {
            perror("calloc errror ");
            return NULL;
        }
    
        new->prev = new;
        new->next = new;
    
        return new;
    }
    

    得到数据

     从键盘上获得数据并返回,形式参数是一个字符串,用来说明获得数据的用途。

    int input_msg(char *msg)
    {   
        int data;
        printf("%s", msg);
        scanf("%d", &data);
        while('
    ' != getchar());
    
        return data;
    }
    

    插入节点

     在任意节点后插入一个节点。

    bool insert_node(p_douoble_crclist front_node, p_douoble_crclist new)
    {
        p_douoble_crclist p_node = front_node;//front_node为前置节点,new是需要插入的节点
        if(NULL == new)//当new为空时,表示需要新创建一个节点插入链表
        {
            int data;
            new = new_node();
            if(NULL == new)
                return false;
    
            new->data = input_msg("Please enter the data to add:");
        }
    
        new->prev = p_node;
        new->next = p_node->next;
        p_node->next = new;
        new->next->prev = new;
    
        return true;
    }
    
    

    打印链表数据

     将链表中的所有数据打印出来。

    void display_node(p_douoble_crclist head)
    {
        p_douoble_crclist pos = head->next;
    
        for(int i = 0; pos != head; i++) //当将链表遍历一遍后就跳出循环
        {
            printf("The data of node %d is:%d
    ", i, pos->data);//每跳一个节点就将其数据打印出来
            pos = pos->next;
        }
    }
    

    查找数据

     查找链表中是否有某个数据,有的话返回该数据所在节点的地址。

    p_douoble_crclist find_data_to_list(p_douoble_crclist head, char *msg)
    {
         p_douoble_crclist fdpos = head->next;
    
        int fdata;
    
        if(msg == NULL)
        {
            fdata = input_msg("Please enter the data you want to look up:");
        }
        else
        {
            fdata = input_msg(msg);
        }
    
        while(fdpos != head)  //遍历链表
        {
            if(fdpos->data != fdata)//每跳一个节点就比较该节点数据是否,是需要查找的。
            {
                fdpos = fdpos->next;
                continue;
            }
            else
            {
                return fdpos;
            }
        }
        return NULL;
    }
    

    删除节点

     删除指定节点

    p_douoble_crclist del_node_to_list(p_douoble_crclist head, p_douoble_crclist del_node)
    {
        p_douoble_crclist dpos = head;
        if(NULL == head)
        {
            return NULL;
        }
    
        while(dpos->next != del_node)
        {
            dpos = dpos->next;
        }
    
        dpos->next = del_node->next;
        del_node->next->prev = dpos;
        del_node->next = del_node->prev = del_node;
    
        return del_node;
    
    }
    

    修改数据

     修改某个节点的数据。

    bool mod_node_data(p_douoble_crclist mod_node)
    {
        int mod_data;
        if(NULL == mod_node)
        {
            return  false;
        }
    
        printf("Change the data to:");
        scanf("%d", &mod_data);
        mod_node->data = mod_data;
        
        return true;
    }
    

    销毁链表

     将链表中的节点空间逐个释放。

    bool distory_list(p_douoble_crclist *head)
    {
        if (head == NULL)
        {
            printf("The list is already empty!!!");
        }
        p_douoble_crclist dist_pos = (*head)->next;
    
        while(dist_pos != (*head))
        {
            dist_pos = dist_pos->next;
            dist_pos->prev->next = NULL;
            dist_pos->prev->prev = NULL;
            free(dist_pos->prev);   //还有一个节点没有释放掉,试了很多方法就是不行
        }
    
        (*head)->next = NULL;
        (*head)->prev = NULL;
        free(*head);
        *head = NULL;
    
        return dist_pos;
    }
    

    测试程序

    int test()
    {
        p_douoble_crclist head = new_node();  
    
        if(NULL == head)
            return -1;
    
        insert_node(head, NULL);
        insert_node(head, NULL);
        insert_node(head, NULL);
        insert_node(head, NULL);
        insert_node(head, NULL);
        insert_node(head, NULL);
        insert_node(head, NULL);
        insert_node(head, NULL);
        display_node(head);
    
        p_douoble_crclist del_node;
        p_douoble_crclist mv_node;
        p_douoble_crclist front_node;
        p_douoble_crclist mod_node;
    
        del_node = find_data_to_list(head, "Mobile data:");
        mv_node  = del_node_to_list(head, del_node);
        display_node(head);
        front_node = find_data_to_list(head, "Inserts the moved data into the leading node:");
        insert_node(front_node, mv_node);
        display_node(head);
    
        mod_node = find_data_to_list(head, "Modify the data:");
        mod_node_data(mod_node);
        display_node(head);
    
        distory_list(&head);
    
        return true;
    }
    
    

    合并两个数据链表

     合并两个数据链表,注意需要优先断开指向head2的指针。

    p_douoble_crclist cont_2_list(p_douoble_crclist head1 , p_douoble_crclist head2)
    {
        if ( head1 == NULL  || head2 == NULL)
        {
            printf("The list is already empty!!
    ");
            return NULL ;
        }
    
        head2->prev->next = head1 ;
        head2->next->prev = head1->prev ;
        head1->prev->next = head2->next ;
        head1->prev = head2->prev ;
    
        head2->next = head2->prev = NULL ;
        return head2;
    }
    

    测试代码

    int test()
        //初始化
        p_douoble_crclist head1 = new_node(0);
        p_douoble_crclist head2 = new_node(0);
    
    
        //添加数据
        for (size_t i = 0; i < 5; i++)
        {
            insert_node(head1 , NULL );
        }
    
        for (size_t i = 0; i < 5; i++)
        {
            insert_node(head2 , NULL );
        }
    
    
        // 显示数据
        printf("*******************************
    ");
        display_node(head1);
        printf("*******************************
    ");
        display_node(head2);
        printf("*******************************
    ");
    
    
        // 链接两个表
        cont_2_list(head1 , head2);
        head2 = NULL ;
        display_node(head1);
        printf("*******************************
    ");
        return true;
    }
    
  • 相关阅读:
    关于C++中的友元函数的总结
    一个使用动态链接库资源出错的难题
    如何在对话框中实现文件拖放功能
    VS2005设置可以在Release模式下调试 .
    6 Tips for Managing Property Files with Spring
    Linux命令行下SSH端口转发设定笔记_leo_百度空间
    Array properties in Spring Framework
    关于前端产品呈现形态及早期推进
    不要等离别的再珍惜,过好每一天啊
    Django snippets: uuid model field
  • 原文地址:https://www.cnblogs.com/ding-ding-light/p/14110848.html
Copyright © 2011-2022 走看看