Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1638585
  • 博文数量: 197
  • 博客积分: 10046
  • 博客等级: 上将
  • 技术积分: 1983
  • 用 户 组: 普通用户
  • 注册时间: 2006-08-07 12:36
个人简介

在外企做服务器开发, 目前是项目经理, 管理两个server开发的项目。不做嵌入式好久了。

文章分类
文章存档

2011年(2)

2010年(6)

2009年(18)

2008年(30)

2007年(100)

2006年(41)

分类: LINUX

2008-10-29 22:32:54

/*
* 我也遵循GPL协议
* A simple single list implementation.
*
* Copyright (C) 2008 Bob Zhang
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/


/* ===================================================================================
* 简单的实现一个单链表的功能
*
* CopyRight reserved by BobZhang bob.zhang2004@gmail.com bobzhang@mxic.com.cn
*
* 功能:
* 模拟struct list_head 的函数格式重新实现自己的单链表操作,全部重新实现
* 倒置list , 比如 header -> a -> b -> c 执行convert函数后 变成 header->c->b->a
*
* 注意:
* 此库模仿struct list_head的实现(include/linux/list.h ),
* 但仅仅是函数名称和一些宏, 名称相同,实现并不相同
* ==================================================================================*/



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



typedef struct node_t {
    void *data_p; //可以兼容所有的数据类型

    struct node_t *next;
}node_t;


typedef struct list_t {
    node_t *header;
    // int size; //元素个数


}list_t;


//初始化一个节点


#define INIT_NODE(node,ptr) do { node->data_p = ptr; node->next = NULL; } while(0)

//声明一个节点


#define DECLARE_NODE(name,ptr) \
    node_t *name = (node_t *)malloc(sizeof(node_t));\
    INIT_NODE(name,ptr);

//声明一个链表


#define DECLARE_LIST(list_name) \
    list_t *list_name = (list_t *)malloc(sizeof(list_t)); \
    INIT_LIST_HEAD(list_name); \


int INIT_LIST_HEAD(list_t *p);
int __list_add(node_t *new,node_t *prev,node_t *next); //中间插入一个新的节点


int list_add(node_t *new,list_t *slist); //加在header的后面


int list_add_tail(node_t *new, list_t *slist); //加在尾巴上


int __list_del(node_t *entry,node_t *prev,node_t *next);//删除单链表上的任意一个节点,当然要有这个节点指针


int list_del(node_t *entry,list_t *slist); //从单项链表中删除某个节点


int list_del_head(list_t *slist); //删除header后面的节点


int convert(list_t *list); //倒置list , 比如 header -> a -> b -> c 执行convert函数后 变成 header->c->b->a


int free_list(list_t *slist); //释放链表




//初始化一个链表


int INIT_LIST_HEAD(list_t *p)
{
    p->header = (node_t *)malloc(sizeof(node_t));
    p->header->next = NULL;

    return 0;
}


//加在prev和next之间


int __list_add(node_t *new,node_t *prev,node_t *next) //中间插入一个新的节点


{
    new->next = next;
    prev->next = new;

    return 0;
}


//加在header的后面


int list_add(node_t *new,list_t *slist)
{
    __list_add(new,slist->header,slist->header->next);

    return 0;
}

//加在尾巴上


int list_add_tail(node_t *new, list_t *slist)
{
    //node_t *rear = NULL;

    node_t *tmp = NULL;

    //遍历到list的尾部


//    rear = slist->header;

//    tmp = slist->header->next;

//    while(tmp) {

//        rear = tmp;

//        tmp = tmp->next;

//    }

//到尾了rear 就是最后一个节点,rear->next=NULL


//不用rear指针

    tmp = slist->header;
    while(tmp->next)
        tmp = tmp->next;
    
    __list_add(new,tmp,tmp->next);

    return 0;
}

//删除单链表上的任意一个节点,当然要有这个节点指针


int __list_del(node_t *entry,node_t *prev,node_t *next)
{
    //三个参数的关系 prev->entry->next


    prev->next = next;

    entry->next = NULL;
    entry->data_p = NULL;

    free(entry);

    return 0;
}


//从单项链表中删除某个节点


//肯定要遍历查找这个节点的前驱节点, 只需更改前驱节点的next指针即可


#if 0
int list_del(node_t *entry,list_t *slist)
{
    //先遍历一次找到他的前驱,因为slist没有prev指针


    node_t *header = slist->header;
    node_t * prev = NULL;
    node_t *this_entry = NULL;

    prev = header;
    this_entry = prev->next;
    if(!this_entry) {
        printf("list empty \n");
        return -1;
    }

    while(this_entry)
    {
        if(this_entry == entry) //找到了,比较指针

        break;

        prev = this_entry;
        this_entry = this_entry->next;
    }

    if(!this_entry) //最终没有找到


    {
        printf("no this node ,please check \n");
        return -1;
    }

    __list_del(this_entry,prev,this_entry->next); //prev -> entry -> entry->next




    return 0;
}

#endif


int list_del(node_t *entry,list_t *slist)
{
    //先遍历一次找到他的前驱,因为slist没有prev指针


    node_t *tmp = slist->header;
    if(!tmp->next) {
        printf("empty list \n");
        return -1;
    }
    
    while(tmp->next)
    {
        if(tmp->next == entry)
            break;
        tmp = tmp->next;
    }
    if(!tmp->next)
    {
        printf("no this node in this list\n");
        return -1;
    }
    
    __list_del(entry,tmp,entry->next);
    
    return 0;
}

//删除header后面的节点


int list_del_head(list_t *slist)
{
    int ret = 0;

    ret = __list_del(slist->header->next,slist->header,slist->header->next->next);

    return ret;
}


//倒置list , 比如 header -> a -> b -> c 执行convert函数后 变成 header->c->b->a


int convert(list_t *list)
{
    node_t *tmp = NULL;
    DECLARE_LIST(tmp_list);
    
    tmp = list->header->next;
    if(!tmp) {
        printf("list empty \n");
        return -1;
    }
    //遍历链表


    while(tmp)
    {
        node_t *next_node = tmp->next; //因为tmp在下行操作后 tmp->next 就等于NULL了,所以这里要记住tmp->next


        list_add(tmp,tmp_list);
        tmp = next_node;
    }

    free(list->header); //释放之前的header


    list->header = tmp_list->header; //原来的链表的header更新一下,是现在新的头



    return 0;
}


//释放链表


int free_list(list_t *slist)
{

    node_t *header = slist->header;

    while(header->next)
    {
        __list_del(header->next,header,header->next->next);
    }

    slist->header = NULL;
    
//释放header节点和list本身

    free(slist->header);
    free(slist);

    return 0;
}


node_t * copy_node(node_t * old_node)
{
    
    node_t * new_node = (node_t *)malloc(sizeof(node_t));
    if(!new_node)
    {
        printf("in copy_node : copy node failure\n");
        return NULL;
    }
    printf("length = %d\n",sizeof(typeof(old_node->data_p)));
    //data_p 由于是泛型指针, 我怎么来处理呢? 如果是整数,直接赋值,如果是char * ,就memcpy即可

    memcpy(new_node->data_p,old_node->data_p,sizeof(typeof(old_node->data_p)));
    new_node->next = NULL;
    
    return 0;
}

//复制一个链表

list_t * copy_list(list_t *src_list)
{
    node_t *tmp = src_list->header->next;
    DECLARE_LIST(new_list);    //已经有header,是新malloc过来的

    
    //现在要遍历src_list,然后依次插入到新的链表中

    if(!tmp) {
        printf("src list empty \n");
        return NULL;
    }
    while(tmp)
    {
        node_t *node = copy_node(tmp);
        if(!node)
        {
            printf("copy list failure\n");
        //错误处理:

            free(new_list);
            
            return NULL;
        }
        list_add(node,new_list);
        tmp = tmp->next;
        
    }
    
    return new_list;
}

    
    
int main(void)
{
    node_t *p = NULL;
    list_t *new_list = NULL;

    DECLARE_LIST(list);
    DECLARE_LIST(list_int);
    DECLARE_LIST(list_dd_pointer);

    DECLARE_NODE(p1,"zhanglinbao");
    DECLARE_NODE(p2,"1234567890");
    DECLARE_NODE(p3,"ABCDEFGHIJKLMN");
    
    int a = 10;
    int b = 20;
    int c = 30;
    
    char *s1 = "12344";
    char *s2 = "abcdefg";
    char *s3 = "xyz";
    
    
    DECLARE_NODE(p4,&a);
    DECLARE_NODE(p5,&b);
    DECLARE_NODE(p6,&c);

    DECLARE_NODE(S1,&s1);
    DECLARE_NODE(S2,&s2);
    DECLARE_NODE(S3,&s3);
    
    
    
    // ---------------------------------------------------------------


    //下面的这些代码都用上面的4个宏来实现了, 看起来简练一些


    // list_t *list = (list_t *)malloc(sizeof(list_t));



    //用宏简化一下这种写法,更简洁


    // node_t *p1 = (node_t *)malloc(sizeof(node_t));


    // node_t *p2 = (node_t *)malloc(sizeof(node_t));


    // node_t *p3 = (node_t *)malloc(sizeof(node_t));



    //初始化链表


    // INIT_LIST_HEAD(list);




    // INIT_NODE(p1,"zhanglinbao");


    // INIT_NODE(p2,"1234567890");


    // INIT_NODE(p3,"ABCDEFGHIJKLMN");


    //-----------------------------------------------------------------



    list_add_tail(p1,list);
    list_add_tail(p2,list);
    list_add_tail(p3,list);

    list_add_tail(p4,list_int);
    list_add_tail(p5,list_int);
    list_add_tail(p6,list_int);
    
    list_add_tail(S1,list_dd_pointer);
    list_add_tail(S2,list_dd_pointer);
    list_add_tail(S3,list_dd_pointer);

    p = list->header->next;
    while(p)
    {
        printf("%s\n",(char *)(p->data_p));
        p=p->next;
    }

    p = list_int->header->next;
    while(p)
    {
        printf("%d\n",*(int *)(p->data_p));
        p = p->next;
    }
    
    p = list_int->header->next;
    while(p)
    {
        printf("%p\n",*(char **)(p->data_p));
        p = p->next;
    }
    printf("s1=%p\n",s1);
    printf("s2=%p\n",s2);
    printf("s3=%p\n",s3);
    
    /* 测试copy list 函数 */
    new_list = copy_list(list);
    if(new_list==NULL)
    {
        printf("copy list failure \n");
        return -1;
    }
    p = new_list->header->next;
    while(p)
    {
        printf("%s\n",(char *)(p->data_p));
        p = p->next;
    }

    
    
    
    printf("\n\n");
    printf("I want to delete the node whose name is %s\n",(char*)(p1->data_p));
    list_del(p1,list); //删除一个节点




    p = list->header->next;
    while(p)
    {
        printf("%s\n",(char *)(p->data_p));
        p=p->next;
    }


    //开始倒置链表


    convert(list);
    printf("\n\nI have converted ok \n");

    p = list->header->next;
    while(p)
    {
        printf("%s\n",(char *)(p->data_p));
        p=p->next;
    }

    free_list(list);

    return 0;
}

阅读(1986) | 评论(2) | 转发(0) |
给主人留下些什么吧!~~

bob_zhang20042008-10-30 17:35:04

其实更简单的办法是直接把child 节点扔到 父节点的后面去。 这样就很直接了。定义链表的时候,也不用定义rear 了。 这种办法就比较直接。

bob_zhang20042008-10-29 22:53:45

其实用 带头结点的单链表实现 栈是太简单了, 非常的自然。 直接在头结点的后面 直接插入就可以了。 里面只有 top , 也不需要专门定义专门的栈底 。 如果 stack->top->next == NULL , 就说明到达栈底了。 根本不用来回挪动指针。 这就是链表带头结点的好处, 考研的里面就有这个题 。 看看考研的辅导书, 还是很有好处的。 呵呵。 从现在开始, 要好好看书。