| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1318 人关注过本帖, 2 人收藏
标题:一个双端链表
只看楼主 加入收藏
lz1091914999
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:四川
等 级:贵宾
威 望:37
帖 子:2011
专家分:5959
注 册:2010-11-1
结帖率:94.64%
收藏(2)
已结贴  问题点数:100 回复次数:14 
一个双端链表
LinkedList.h
程序代码:
/*
** 一个双端链表的实现,其结点存储的是数据的指针,所以在跨函数使用时必须
** 保证数据是静态或动态分配的。
*/

#ifndef LINKED_LIST_H
#define LINKED_LIST_H

typedef struct NodeTag       Node;
typedef struct LinkedListTag LinkedList;

struct NodeTag {
    Node* prev;     /* 前一个结点 */
    Node* next;     /* 后一个结点 */
    void* data;     /* 数据的指针 */
};

struct LinkedListTag {
    Node*    head;  /* 头结点 */
    Node*    tail;  /* 尾结点 */
    Node*    cur;   /* 当前结点 */
    int      size;  /* 链表大小 */
};

LinkedList* Create     (void);                         /* 创建一个链表,成功返回该链表的指针,否则返回NULL */
void        Destroy    (LinkedList* list);             /* 销毁一个链表,之后该链表便不能再使用 */
void        Clear      (LinkedList* list);             /* 清空链表中的所有元素 */
int         IsEmpty    (LinkedList* list);             /* 如果当前链表为空则返回非0,否则返回0 */
int         Size       (LinkedList* list);             /* 获得链表的大小(元素总个数) */
void        Begin      (LinkedList* list);             /* 将当前位置移动到链表的开始 */
void        End        (LinkedList* list);             /* 将当前位置移动到链表的最后 */
void        MoveNext   (LinkedList* list);             /* 将当前位置向后移动一个位置 */
void        MovePrev   (LinkedList* list);             /* 将当前位置向前移动一个位置 */
int         HasNext    (LinkedList* list);             /* 如果当前位置之后还有元素则返回非0,否则返回0 */
int         HasPrev    (LinkedList* list);             /* 如果当前位置之前还有元素则返回非0,否则返回0 */
void*       Current    (LinkedList* list);             /* 返回当前位置的元素 */
int         AddBack    (LinkedList* list, void* data); /* 将元素添加到链表末尾,成功返回非0,否则返回0 */
int         AddFront   (LinkedList* list, void* data); /* 将元素添加到链表前端,成功返回非0,否则返回0 */
void*       RemoveBack (LinkedList* list);             /* 将元素从末端移除并返回该元素,如果链表为空则返回NULL */
void*       RemoveFront(LinkedList* list);             /* 将元素从前端移除并返回该元素,如果链表为空则返回NULL */

#endif /* LINKED_LIST_H */

LinkedList.c
程序代码:
#include "LinkedList.h"
#include <stdlib.h>

#ifndef NULL
#define NULL ((void*)0)
#endif

/* 创建一个链表,成功返回该链表的指针,否则返回NULL */
LinkedList* Create(void)                         
{
    LinkedList* list = (LinkedList*)malloc(sizeof(LinkedList));
    if (!list) return NULL;
    
    list->head = NULL;
    list->tail = NULL;
    list->cur  = NULL;
    list->size = 0;
    
    return list;
}

/* 销毁一个链表,之后该链表便不能再使用 */
void Destroy(LinkedList* list)
{
    Clear(list);
    free(list);
}

/* 清空链表中的所有元素 */
void Clear(LinkedList* list)
{
    while (RemoveBack(list)) ;
}

/* 如果当前链表为空则返回非0,否则返回0 */
int IsEmpty(LinkedList* list)
{
    return list->size == 0;
}

/* 获得链表的大小(元素总个数) */
int Size(LinkedList* list)
{
    return list->size;
}

/* 将当前位置移动到链表的开始 */
void Begin(LinkedList* list)
{
    list->cur = list->head;
}

/* 将当前位置移动到链表的最后 */
void End(LinkedList* list)
{
    list->cur = list->tail;
}
/* 将当前位置向后移动一个位置 */
void MoveNext(LinkedList* list)
{
    list->cur = list->cur->next;
}

/* 将当前位置向后移动一个位置 */
void MovePrev(LinkedList* list)
{
    list->cur = list->cur->prev;
}

/* 如果当前位置之后还有元素则返回非0,否则返回0 */
int HasNext(LinkedList* list)
{
    if (!list->cur) return 0;
    if (list->cur == list->tail) return 1;
    return list->cur->next != NULL;
}

/* 如果当前位置之前还有元素则返回非0,否则返回0 */
int HasPrev(LinkedList* list)
{
    if (!list->cur) return 0;
    if (list->cur == list->head) return 1;
    return list->cur->prev != NULL;
}

/* 返回当前位置的元素 */
void* Current(LinkedList* list)
{
    return list->cur->data;
}

/* 将元素添加到链表末尾,成功返回非0,否则返回0 */
int AddBack(LinkedList* list, void* data)
{
    Node* node = (Node*)malloc(sizeof(Node));
    if (!node) return 0;
    
    node->data = data;
    if (list->tail) {
        list->tail->next = node;
        node->prev       = list->tail;
        node->next       = NULL;
    } else {
        node->next = NULL;
        node->prev = NULL;
        list->head = node;
    }
    list->tail = node;
    
    return ++list->size;
}

/* 将元素添加到链表前端,成功返回非0,否则返回0 */
int AddFront(LinkedList* list, void* data)
{
    Node* node = (Node*)malloc(sizeof(Node));
    if (!node) return 0;
    
    node->data = data;
    if (list->head) {
        list->head->prev = node;
        node->next       = list->head;
        node->prev       = NULL;
    } else {
        node->next = NULL;
        node->prev = NULL;
        list->tail = node;
    }
    list->head = node;
    
    return ++list->size;
}

/* 将元素从末端移除并返回该元素,如果链表为空则返回NULL */
void* RemoveBack(LinkedList* list)
{
    Node* temp;
    void* data;
    
    if (!list->size) return NULL;
    
    temp = list->tail;
    data = list->tail->data;
    
    if (list->head == list->tail) {
        list->head = NULL;
        list->tail = NULL;
        list->cur  = NULL;
    } else {
        list->tail       = list->tail->prev;
        list->tail->next = NULL;
    }
    --list->size;
    free(temp);
    
    return data;
}

/* 将元素从前端移除并返回该元素,如果链表为空则返回NULL */
void* RemoveFront(LinkedList* list)
{
    Node* temp;
    void* data;
    
    if (!list->size) return NULL;
    
    temp = list->head;
    data = list->head->data;
    
    if (list->head == list->tail) {
        list->head = NULL;
        list->tail = NULL;
        list->cur  = NULL;
    } else {
        list->head       = list->head->next;
        list->head->prev = NULL;
    }
    --list->size;
    free(temp);
    
    return data;
}

LinkedListTest.c
程序代码:
#include "LinkedList.h"
#include <stdio.h>

void Traverse(LinkedList* list)
{
    for (Begin(list); HasNext(list); MoveNext(list))
        printf("%d ", *(int*)Current(list));
    putchar('\n');
}

void RTraverse(LinkedList* list)
{
    for (End(list); HasPrev(list); MovePrev(list))
        printf("%d ", *(int*)Current(list));
    putchar('\n');
}

int main(void)
{
    LinkedList* list = Create();
    int i;
    
    int array1[10];
    int array2[10];
    
    for (i = 0; i < 10; ++i) {
        array1[i] = i + 1;
        array2[i] = i + 10 + 1;
        AddBack(list, &array1[i]);
    }
    puts("1:");
    Traverse(list);
    RTraverse(list);
    printf("Size: %d\n", Size(list));
    
    AddBack(list, &array2[0]);
    puts("2:");
    Traverse(list);
    RTraverse(list);
    printf("Size: %d\n", Size(list));
    
    AddFront(list, &array2[1]);
    puts("3:");
    Traverse(list);
    RTraverse(list);
    printf("Size: %d\n", Size(list));
    
    RemoveBack(list);
    puts("4:");
    Traverse(list);
    RTraverse(list);
    printf("Size: %d\n", Size(list));
    
    RemoveFront(list);
    puts("5:");
    Traverse(list);
    RTraverse(list);
    printf("Size: %d\n", Size(list));
    
    Clear(list);
    for (i = 0; i < 10; ++i)
        AddFront(list, &array2[i]);
    puts("6:");
    Traverse(list);
    RTraverse(list);
    printf("Size: %d\n", Size(list));
    
    Destroy(list);
    return 0;
}
/*
1:
1 2 3 4 5 6 7 8 9 10
10 9 8 7 6 5 4 3 2 1
Size: 10
2:
1 2 3 4 5 6 7 8 9 10 11
11 10 9 8 7 6 5 4 3 2 1
Size: 11
3:
12 1 2 3 4 5 6 7 8 9 10 11
11 10 9 8 7 6 5 4 3 2 1 12
Size: 12
4:
12 1 2 3 4 5 6 7 8 9 10
10 9 8 7 6 5 4 3 2 1 12
Size: 11
5:
1 2 3 4 5 6 7 8 9 10
10 9 8 7 6 5 4 3 2 1
Size: 10
6:
20 19 18 17 16 15 14 13 12 11
11 12 13 14 15 16 17 18 19 20
Size: 10
*/

 
写这个主要是想给“有容就大”看看,我可是收了人家100分呢。
因为不能使用模板,所以我把每个结点的元素类型设置成了void*,这样就需要在获得元素值之后用强转来恢复其本意。而且跨函数使用时,数据不能是自动变量,必须是静态或动态分配的数据,这在头文件里有描述。
灵感有些来自于Java的util包里的LinkedList。不过遍历方式上还是有些不同的。

[ 本帖最后由 lz1091914999 于 2012-11-27 19:07 编辑 ]
收到的鲜花
搜索更多相关主题的帖子: 动态 
2012-11-27 18:55
jk_love
Rank: 8Rank: 8
等 级:蝙蝠侠
威 望:1
帖 子:196
专家分:965
注 册:2012-10-22
收藏
得分:8 
  研究学习
2012-11-27 19:29
wp231957
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:神界
等 级:贵宾
威 望:423
帖 子:13688
专家分:53332
注 册:2012-10-18
收藏
得分:8 
不懂链表   标记
收到的鲜花
  • newdos2012-11-28 13:54 送鲜花  1朵   附言:有空学习一下啊。 数据结构基础。

DO IT YOURSELF !
2012-11-27 19:38
pauljames
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:千里冰封
威 望:9
帖 子:1555
专家分:10000
注 册:2011-5-8
收藏
得分:8 
mark

经常不在线不能及时回复短消息,如有c/单片机/运动控制/数据采集等方面的项目难题可加qq1921826084。
2012-11-27 21:01
有容就大
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:东土大唐
等 级:版主
威 望:74
帖 子:9048
专家分:14309
注 册:2011-11-11
收藏
得分:8 
有劳L版费心了 呵呵 先好好看下你给的代码。

梅尚程荀
马谭杨奚







                                                       
2012-11-27 21:21
青春无限
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:江苏
等 级:贵宾
威 望:24
帖 子:3452
专家分:19340
注 册:2012-3-31
收藏
得分:8 
学习

学 会看代码…学习写程序…学会搞开发…我的目标!呵呵是不是说大话啊!!一切皆可能
2012-11-27 21:34
yuccn
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:何方
等 级:版主
威 望:167
帖 子:6815
专家分:42393
注 册:2010-12-16
收藏
得分:8 
好像有分拿,我就回复了

我行我乐
公众号:逻辑客栈
我的博客:
https://blog.yuccn. net
2012-11-27 21:37
bccnyouke
Rank: 2
等 级:论坛游民
帖 子:26
专家分:49
注 册:2012-11-23
收藏
得分:8 
写的还可以,有那么点linux的味道
2012-11-27 21:42
youngdavid
Rank: 7Rank: 7Rank: 7
等 级:黑侠
帖 子:107
专家分:698
注 册:2012-9-24
收藏
得分:8 
mark+1
2012-11-27 22:33
逸枫
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:33
专家分:113
注 册:2012-6-10
收藏
得分:8 
早点出现就好啦,那个时候有类似的作业。。
2012-11-27 23:22
快速回复:一个双端链表
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.032147 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved