圣龙扬特-AVR电子
标题:
[源代码] C语言单向链表
[打印本页]
作者:
avrbase_lei
时间:
2013-4-12 18:36
标题:
[源代码] C语言单向链表
本帖最后由 avrbase_lei 于 2013-4-12 18:38 编辑
再贴点儿工作用到的代码。单向链表。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
typedef unsigned char snl_u8;
typedef signed char snl_s8;
typedef unsigned short int snl_u16;
typedef signed short int snl_s16;
typedef unsigned int snl_u32;
typedef signed int snl_s32;
typedef char snl_char;
typedef unsigned short snl_wchar;
typedef enum {snl_false, snl_true} snl_bool;
typedef struct single_node_list{
struct single_node_list *next;
void *vp;
}SingleNodeList_t;
复制代码
在定义些函数接口,方便调试。
#define snl_trace printf
#define snl_malloc malloc
#define snl_mfree free
#define snl_assert assert
#define snl_memset memset
#define snl_memcpy memcpy
#define snl_memcmp memcmp
复制代码
接着就是源代码了。
/*******************************************************************************
** 函数: snl_alloc_new
** 功能: 申请一个新的节点内存
** 作者: avrbase_lei
*******/
static SingleNodeList_t *snl_alloc_new(void)
{
SingleNodeList_t *newnode = NULL;
newnode = (SingleNodeList_t*)snl_malloc(sizeof(SingleNodeList_t));
snl_assert(NULL != newnode);
snl_memset((void*)newnode, 0, sizeof(SingleNodeList_t));
return newnode;
}
复制代码
/*******************************************************************************
** 函数: snl_insert
** 功能: 在链表上插入一个新的节点.
** 入参: rootpp 指向根节点的指针.
** addvp 需要插入链表的数据地址.
** front_insert 是否插入在匹配到的节点的前面.
** private_compare 比较函数, 比较成功后依front_insert决定插入位置.
** 若直到链表尾都未匹配成功则默认插入链表为尾.
** 若private_compare为空则插入链表尾.
** 返回: 返回插入结果.
** 作者: avrbase_lei
*******/
static snl_bool snl_insert(
SingleNodeList_t **rootpp,
void *addvp,
void *compare_vp,
snl_bool front_insert,
snl_bool (*private_compare)(void *, void *))
{
snl_bool inserted = snl_false;
snl_bool is_root_pos = snl_true;
SingleNodeList_t *newnode = NULL;
SingleNodeList_t *currnode = NULL, *prevnode = NULL;
do{
if(NULL == rootpp)
break;
newnode = snl_alloc_new();
if(NULL == newnode)
break;
newnode->vp = addvp;
if(NULL == private_compare || NULL == compare_vp)
{
if(NULL == *rootpp)
{
*rootpp = newnode;
}
else
{
currnode = *rootpp;
while(NULL != currnode->next)
{
currnode = currnode->next;
}
currnode->next = newnode;
}
inserted = snl_true;
break;
}
currnode = *rootpp;
is_root_pos = snl_true;
inserted = snl_false;
while(NULL != currnode && !inserted)
{
if(private_compare(currnode->vp, compare_vp))
{
//如果是根节点匹配到了, 则根节点要指向下一个节点
if(is_root_pos)
{
if(front_insert)
{
newnode->next = *rootpp;
*rootpp = newnode;
}
else
{
newnode->next = (*rootpp)->next;
(*rootpp)->next = newnode;
}
}
else
{
if(front_insert)
{
newnode->next = currnode;
prevnode->next = newnode;
}
else
{
newnode->next = currnode->next;
currnode->next = newnode;
}
}
inserted = snl_true;
}
else
{
prevnode = currnode;
currnode = currnode->next;
is_root_pos = snl_false;
}
}
if(!inserted)
{
prevnode->next = newnode;
inserted = snl_true;
}
}while(0);
return inserted;
}
复制代码
/*******************************************************************************
** 函数: snl_delete
** 功能: 删除链表上snl_compare匹配到的指定的节点
** 如果比较函数为空则执行全部删除功能.
** 入参: rootpp 根节点
** com_node_data_p 用于参与匹配的数据
** traval_del 是否遍历删除链表中的节点. 否则删除离根节点最近的节点
** private_compare 数据匹配函数, 其返回值用于决定是否删除
** private_delete 数据删除函数, 本参数必须非空, 否则无法删除任何数据
** 返回: 返回删除的节点个数
** 作者: avrbase_lei
*******/
static snl_u32 snl_delete(
SingleNodeList_t **rootpp,
void *cmp_node_data_p,
snl_bool travel_del,
snl_bool (*private_compare)(void *, void *),
void (*private_delete)(void *))
{
snl_u32 deleted_ct = 0;
snl_bool is_del_root = snl_true;
SingleNodeList_t *currnode = NULL, *prevnode = NULL, *delnode = NULL;
do{
if(NULL == rootpp)
break;
if(NULL == private_delete)
break;
if(NULL == private_compare)
{
currnode = *rootpp;
while(NULL != currnode)
{
delnode = currnode;
currnode = currnode->next;
private_delete(delnode->vp);
snl_mfree(delnode);
deleted_ct ++;
}
*rootpp = NULL;
break;
}
if(NULL == cmp_node_data_p)
break;
currnode = *rootpp;
is_del_root = snl_true;
while(NULL != currnode)
{
if(private_compare(currnode->vp, cmp_node_data_p))
{
//如果是根节点匹配到了, 则根节点要指向下一个节点
if(is_del_root)
{
*rootpp = prevnode = currnode->next;
}
else
{
prevnode->next = currnode->next;
is_del_root = snl_false;
}
//当前节点指向下一个节点
delnode = currnode;
currnode = currnode->next;
//删除节点
private_delete(delnode->vp);
snl_mfree(delnode);
deleted_ct ++;
//非遍历删除则中断循环
if(!travel_del)
break;
}
else
{
prevnode = currnode;
currnode = currnode->next;
is_del_root = snl_false;
}
}
}while(0);
return deleted_ct;
}
复制代码
估计排版很恶心。
作者:
avrbase_lei
时间:
2013-4-12 18:41
还要自己测试下。
<P>/*******************************************************************************
** 函数: test_print_list
** 功能: 测试用的打印链表所有数据信息的函数
** 入参: rootpp 根节点指针
** 返回:
** 作者: avrbase_lei
*******/
static void test_print_list(SingleNodeList_t **rootpp)
{
SingleNodeList_t *tmpnode = *rootpp;</P>
<P> snl_trace("print list:\r\n value: ");
while(NULL != tmpnode)
{
snl_trace("%d ", (snl_u32)tmpnode->vp);
tmpnode = tmpnode->next;
}
snl_trace("\r\nprint end.\r\n");
}
</P>
复制代码
这排版,毫无美观可言。
/*******************************************************************************
** 函数: test_delete
** 功能: 测试用的节点数据删除函数. 函数体可以为空
** 入参: nodevp 节点指针所指向的数据地址
** 返回:
** 作者: avrbase_lei
*******/
static void test_delete(void *nodevp)
{
/* do nothing. */
}
复制代码
/*******************************************************************************
** 函数: test_compare
** 功能: 测试用的比较函数
** 入参: node 节点指针
** cpdt 参与匹配的数据
** 返回: 返回匹配结果
** 作者: avrbase_lei
*******/
static snl_bool test_compare(void *nodevp, void *cpdtp)
{
if(NULL == cpdtp || NULL == nodevp)
return snl_false;
return (snl_bool)((snl_u32)(nodevp) == (snl_u32)cpdtp);
}
复制代码
/*******************************************************************************
** 函数: test_main
** 功能: 测试入口函数
** 入参:
** 返回:
** 作者: avrbase_lei
*******/
void test_main(void)
{
const snl_u32 test_loop_ct = 5;
snl_u32 i, total, cmpdat;
SingleNodeList_t *rootp = NULL;
//insert
for(i=0; i<test_loop_ct; i++)
{
total = snl_insert(&rootp, (void*)i, NULL, snl_false, NULL);
}
//print
test_print_list(&rootp);
//delete
for(i=0; i<test_loop_ct; i++)
{
cmpdat = rand()%test_loop_ct;
snl_trace("%dst delete, to be delete value is %d. \r\n", i, cmpdat);
cmpdat = snl_delete(&rootp, (void *)cmpdat, snl_false, test_compare, test_delete);
snl_trace("snl_delete return %d.\r\n", cmpdat);
test_print_list(&rootp);
}
//free all
snl_delete(&rootp, NULL, snl_true, NULL, test_delete);
test_print_list(&rootp);
}
复制代码
int main(int argc, char **argv)
{
test_main();
printf("程序运行结束!\r\n");
getchar();
return 0;
}
复制代码
欢迎光临 圣龙扬特-AVR电子 (http://avr.cnta.net/)
Powered by Discuz! X2.5