曾经的笔记迁移__通用链表网络版

21 篇文章 0 订阅

C通用链表库(1.0版) 
转载自网络。
 
本链表库可以使用CodeBlocks(MingW)和VC系列编译器进行编译,为单向带头尾的链表,封装后使用起来很简单,实现了链表的增,删,改,排序,清空,遍历等常用操作,可进行元素的前插和尾插,还有两个功能,插入排序和清除重复元素,准备在下一版实现。
头文件:list.h
#ifndef LIST_H_H
#define LIST_H_H
#include <stdio.h>
#include <malloc.h>
#include <string.h>
typedef struct clist *List;
typedef int (*compare)(void *ndata, void *data);
typedef void (*dofunc)(void *ndata);
typedef int (*lpf0)(List l, void *data);
typedef int (*lpf1)(List l, void *data, compare pfunc);
typedef List (*lpf2)(List l);
typedef void (*lpf3)(List l);
typedef void (*lpf4)(List l, dofunc pfunc);
typedef int (*lpf5)(List l, unsigned int index, void *new_data);
typedef void (*lpf6)(List l, compare pfunc);
typedef int (*lpf7)(List l, unsigned int index);
typedef struct cnode
{
 void *data;
 struct cnode *next;
}node, *Node;
typedef struct clist
{
 Node head;
 Node tail;
 unsigned int size;
 unsigned int data_size;
 lpf0 add_back;
 lpf0 add_front;
 lpf1 delete_node;
 lpf1 have_same;
 lpf4 foreach;
 lpf3 clear;
 lpf2 destroy;
 lpf5 modify_at;
 lpf6 sort;
 lpf7 delete_at;
}list;
//初始化链表
List list_init(unsigned int data_size);        
int  list_add_back(List l, void *data);
int  list_add_front(List l, void *data);
int  list_delete_node(List l, void *data, compare pfunc);
int  list_delete_at(List l, unsigned int index);
int  list_modify_at(List l, unsigned int index, void *new_data);
int  list_have_same(List l, void *data, compare pfunc);
void list_foreach(List l, dofunc doit);
void list_sort(List l, compare pfunc);
void list_clear(List l);
//释放链表
List list_destroy(List l);
#endif
----------------------------------------------------------------------------------------------------------------------------------------
实现文件:list_impl.c
#include "list.h"
/// 文件:list_impl.c
/// 功能:实现链表的基本操作
/// 作者:bluewind
/// 完成时间:2011.5.29
/// 修改时间:2011.5.31, 2011.7.2
/// 修改备注:在头节点处添加一个空节点,可以优化添加、删除节点代码
///  再次修改,链表增加节点数据data_size,限制数据大小,修改了
///  添加复制数据代码,修正重复添加节点后释放节点的Bug,添加了前
///  插、排序和遍历功能,7.3 添加tail尾指针,改进后插法性能,并改名
/// --------------------------------------------------------------
void swap_data(Node n1, Node n2);
/// --------------------------------------------------------------
//  函数名:list_init
//  功能:  链表初始化
//  参数:  无 
//  返回值:已初始化链表指针
//  备注:  链表本身动态分配,由list_destroy函数管理释放
/// --------------------------------------------------------------
List list_init(unsigned int data_size)
{
 List list = (List) malloc(sizeof(struct clist));
 if(list != NULL)                                        //内存分配成功
 {
  list->head = (Node) malloc(sizeof(node));           //为头节点分配内存
  if(list->head)          //内存分配成功
  {
   list->head->data = NULL;      //初始化头节点
   list->head->next = NULL;
   list->data_size  = data_size;
   list->tail = list->head;
   list->size = 0;
   
   list->add_back  = list_add_back;   //初始化成员函数
   list->add_front  = list_add_front;
   list->delete_node = list_delete_node;
   list->delete_at  = list_delete_at;
   list->modify_at  = list_modify_at;
   list->have_same  = list_have_same;
   list->foreach  = list_foreach;
   list->clear   = list_clear;
   list->sort   = list_sort;
   list->destroy  = list_destroy;
  }
 }
 return list;
}
/// --------------------------------------------------------------
//  函数名:list_add_back
//  功能:  添加链表结点 (后插法)
//  参数:  l--链表指针,data--链表数据指针,可为任意类型 
//  返回值:int型,为1表示添加成功,为0表示添加失败
//  备注:  如果链表本身为空或是分配节点内存失败,将返回0
/// --------------------------------------------------------------
int  list_add_back(List l, void *data)
{
 Node new_node = (Node) malloc(sizeof(node));
 
 if(l != NULL && new_node != NULL)  //链表本身不为空,且内存申请成功
 {
  new_node->data = malloc(l->data_size);
  memcpy(new_node->data, data, l->data_size);
  new_node->next = NULL;
  l->tail->next = new_node;   //添加节点
  l->tail = new_node;     //记录尾节点位置
  l->size ++;       //链表元素总数加1
  
  return 1;
 }
 
 return 0;
}
/// --------------------------------------------------------------
//  函数名:list_add_front
//  功能:  添加链表结点 (前插法)
//  参数:  l--链表指针,data--链表数据指针,可为任意类型 
//  返回值:int型,为1表示添加成功,为0表示添加失败
//  备注:  如果链表本身为空或是分配节点内存失败,将返回0
/// --------------------------------------------------------------
int list_add_front(List l, void *data)
{
 Node new_node = (Node) malloc(sizeof(node));
 
 if(l != NULL && new_node != NULL)
 {
  new_node->data = malloc(l->data_size);
  memcpy(new_node->data, data, l->data_size);
  new_node->next = l->head->next;
  l->head->next = new_node;
  if(!l->size)        //记录尾指针位置
   l->tail = new_node;
  l->size ++;
  
  return 1;
 }
 
 return 0;
}
/// --------------------------------------------------------------
//  函数名:list_delete_node
//  功能:删除链表结点
//  参数:l--链表指针,data--链表数据指针,可为任意类型
//        *pfunc为指向一个数据类型比较的函数指针
//  返回值:int型,为1表示删除成功,为0表示没有找到匹配数据
//  备注:*pfunc函数接口参数ndata为节点数据,data为比较数据,返回为真表示匹配数据
/// --------------------------------------------------------------
int  list_delete_node(List l, void *data, int (*pfunc)(void *ndata, void *data))
{
 if(l != NULL)
 {
  Node prev = l->head;      //前一个节点
  Node curr = l->head->next;     //当前节点
  
  while(curr != NULL)
  {
   if(pfunc(curr->data, data))    //如果找到匹配数据
   {
    if(curr == l->tail)     //如果是删除尾节点
     l->tail = prev;
    prev->next = prev->next->next;  //修改前节点next指针指向下下个节点
    
    free(curr->data);     //释放节点数据
    free(curr);       //释放节点
    
    l->size--;       //链表元素总数减1
    return 1;       //返回真值
   }
   prev = prev->next;      //没有找到匹配时移动前节点和当前节点
   curr = curr->next;
  }
 }
 
 return 0;         //没有找到匹配数据
}
/// --------------------------------------------------------------
//  函数名:list_delete_at
//  功能:  修改链表节点元素值
//  参数:  l--链表指针,index--索引值, 范围(0 -- size-1) 
//  返回值:int型,为1表示删除成功,为0表示删除失败
//  备注:  如果链表本身为空或是index为非法值,将返回0
/// --------------------------------------------------------------
int list_delete_at(List l, unsigned int index)
{
 unsigned int cindex = 0;
 if(l != NULL && index >= 0 && index < l->size)
 {
  Node prev = l->head;      //前一个节点
  Node curr = l->head->next;     //当前节点
  
  while(cindex != index)
  {
   prev = prev->next;
   curr = curr->next;
   cindex ++;
  }
  if(index == (l->size) - 1)
   l->tail = prev;
  prev->next = prev->next->next;
  free(curr->data);
  free(curr);
  l->size --;
  return 1;
 }
 return 0;
}
/// --------------------------------------------------------------
//  函数名:list_modify_at
//  功能:  修改链表节点元素值
//  参数:  l--链表指针,index--索引值, 范围(0 -- size-1) 
//   data--链表数据指针
//  返回值:int型,为1表示修改成功,为0表示修改失败
//  备注:  如果链表本身为空或是index为非法值,将返回0
/// --------------------------------------------------------------
int list_modify_at(List l, unsigned int index, void *new_data)
{
 unsigned int cindex = 0;
 if(l != NULL && index >= 0 && index < l->size )  //非空链表,并且index值合法
 {
  Node curr = l->head->next;
  while(cindex != index)
  {
   curr = curr->next;
   cindex ++;
  }
  memcpy(curr->data, new_data, l->data_size);
  return 1;
 }
 return 0;
}
/// --------------------------------------------------------------
//  函数名:list_sort
//  功能:  链表排序
//  参数:  l--链表指针,*pfunc为指向一个数据类型比较的函数指针
//  返回值:无
//  备注:  使用简单选择排序法,相比冒泡法每次交换,效率高一点
/// --------------------------------------------------------------
void list_sort(List l, compare pfunc)
{
 if(l != NULL)
 {
  Node min, icurr, jcurr;
  icurr = l->head->next;
  while(icurr)
  {
   min = icurr;        //记录最小值
   jcurr = icurr->next;      //内循环指向下一个节点
   while(jcurr)
   {
    if(pfunc(min->data, jcurr->data))  //如果找到n+1到最后一个元素最小值
     min = jcurr;      //记录下最小值的位置
    jcurr = jcurr->next;
   }
   if(min != icurr)       //当最小值位置和n+1元素位置不相同时
   {
    swap_data(min, icurr);     //才进行交换,减少交换次数
   }
   icurr = icurr->next;
  }
 }
}
void swap_data(Node n1, Node n2)
{
 void *temp;
 temp = n2->data;
 n2->data = n1->data;
 n1->data = temp;
}


int list_have_same(List l, void *data, int (*pfunc)(void *ndata, void *data))
{
 if(l != NULL)
 {
  Node curr;
  for(curr = l->head->next; curr != NULL; curr = curr->next)
  {
   if(pfunc(curr->data, data))
   {
    return 1;
   }
  }
 }
 return 0;
}
/// --------------------------------------------------------------
//  函数名:list_foreach
//  功能:  遍历链表元素
//  参数:  l--链表指针,doit为指向一个处理数据的函数指针 
//  返回值:无
//  备注:  doit申明为void (*dofunc)(void *ndata)原型
/// --------------------------------------------------------------
void list_foreach(List l, dofunc doit)
{
 if(l != NULL)
 {
  Node curr;
  for(curr = l->head->next; curr != NULL; curr = curr->next)
  {
   doit(curr->data);
  }
 }
}
/// --------------------------------------------------------------
//  函数名:list_clear
//  功能:  清空链表元素
//  参数:  l--链表指针
//  返回值:无
// 备注: 没有使用先Destroy再Init链表的办法,直接实现
/// --------------------------------------------------------------
void list_clear(List l)
{
 if(l != NULL)
 {
  Node temp;
  Node curr = l->head->next;
  while(curr != NULL)
  {
   temp = curr->next; 
   
   free(curr->data);    //释放节点和数据
   free(curr);
   
   curr = temp;
  }
  l->size = 0;      //重置链表数据
  l->head->next = NULL;
  l->tail = l->head;
 }
}
/// --------------------------------------------------------------
//  函数名:list_destroy
//  功能:  释放链表
//  参数:  l--链表指针
//  返回值:空链表指针
/// --------------------------------------------------------------
List list_destroy(List l)
{
 if(l != NULL)
 {
  Node temp;
  while(l->head)
  {
   temp = l->head->next;
   
   if(l->head->data != NULL)   //如果是头节点就不释放数据空间
    free(l->head->data);   //先释放节点数据(但是节点数据里也有指针?)
   free(l->head);      //再释放节点
   
   l->head = temp;
  }
  free(l);        //释放链表本身占用空间
  l = NULL;
 }
 return l;
}
-----------------------------------------------------------------------------------------------------------------------------------------------------------
测试用例:main.c
#include "..\list.h"
#include <stdio.h>
typedef struct tag_msg
{
        int x;
}msg, *Msg;
typedef struct foo
{
 char a;
 char b;
 char c;
 char d;
 char e;
}Foo, *Pfoo;
int compare_data(void *ndata, void *data);
void show_data(void *ndata);
int compare2(void *ndata, void *data);
int main()
{
        List list = NULL;
        Node current;
        Msg m1, m2, m3, m4, m5;
  msg m6;
  Foo f1;
        unsigned int i;
  unsigned int data_size;
        
  data_size = sizeof(msg);
        list = list_init(data_size);
        
        m1 = (Msg) malloc(sizeof(msg));
        m2 = (Msg) malloc(sizeof(msg));
        m3 = (Msg) malloc(sizeof(msg));
        m4 = (Msg) malloc(sizeof(msg));
        m5 = (Msg) malloc(sizeof(msg));
        
        m1->x = 100;
        m2->x = 200;
        m3->x = 300;
        m4->x = 400;
        m5->x = 500;
  m6.x  = 600;
  f1.a = 2;
  f1.b = 1;
  f1.c = 0;
  f1.d = 0;
  f1.e = 0;
        
        //添加测试
  list->add_front(list, m1);
  list->add_front(list, m2);
  list->add_front(list, m3);
  list->add_front(list, m4);
  list->add_back(list, m2);
  list->add_back(list, m3);
  list->add_back(list, &m6);
  list->add_back(list, &f1);
  free(m1);
        current = list->head->next;
        for(i = 0; i < (list->size); i++)
        {
                printf("data of msg is %d\n", 
                        ((Msg)(current->data))->x);
                
                current = current->next;
        }
        
        //删除测试
        if(list_delete_node(list, &m6, compare_data))
        {
                printf("\nDelete node OK!\n");
        }
        else
        {
                printf("\nNode data not found!\n");
        }
  list->add_back(list, m4);
  //清空测试
  //list->clear(list);
  //修改测试
  if(list->modify_at(list, 6, m2))
  {
   printf("\nModity data OK!\n\n");
  }
  else
  {
   printf("\nModify data faile!\n\n");
  }
  //list_delete_at(list, 0);
  //list->add_back(list, m2);
  list->add_back(list, &m6);
  list->add_front(list, &f1);
  list->add_back(list, &f1);
       
  list->foreach(list, show_data);        
        
  //排序测试
  list_sort(list, compare2);
  printf("sort after:\n");
  list->foreach(list, show_data);
        list_destroy(list);
        
  free(m4);
        free(m5);
        
        return 0;
}
//实现数据比较
int compare_data(void *ndata, void *data)
{
        if(((Msg)(ndata))->x == ((Msg)(data))->x)
        {
                return 1;
        }
        return 0;
}
int compare2(void *ndata, void *data)
{
 if( ((Msg)ndata)->x > ((Msg)data)->x )
  return 1;
 return 0;
}
//实现遍历数据, 用于list->foreach
void show_data(void *ndata)
{
 printf("data of msg is %d\n", 
                        ((Msg)(ndata))->x);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 内容概要 《计算机试卷1》是一份综合性的计算机基础和应用测试卷,涵盖了计算机硬件、软件、操作系统、络、多媒体技术等多个领域的知识点。试卷包括单选题和操作应用两大类,单选题部分测试学生对计算机基础知识的掌握,操作应用部分则评估学生对计算机应用软件的实际操作能力。 ### 适用人群 本试卷适用于: - 计算机专业或信息技术相关专业的学生,用于课程学习或考试复习。 - 准备计算机等级考试或职业资格认证的人士,作为实战演练材料。 - 对计算机操作有兴趣的自学者,用于提升个人计算机应用技能。 - 计算机基础教育工作者,作为教学资源或出题参考。 ### 使用场景及目标 1. **学习评估**:作为学校或教育机构对学生计算机基础知识和应用技能的评估工具。 2. **自学测试**:供个人自学者检验自己对计算机知识的掌握程度和操作熟练度。 3. **职业发展**:帮助职场人士通过实际操作练习,提升计算机应用能力,增强工作竞争力。 4. **教学资源**:教师可以用于课堂教学,作为教学内容的补充或学生的课后练习。 5. **竞赛准备**:适合准备计算机相关竞赛的学生,作为强化训练和技能检测的材料。 试卷的目标是通过系统性的题目设计,帮助学生全面复习和巩固计算机基础知识,同时通过实际操作题目,提高学生解决实际问题的能力。通过本试卷的学习与练习,学生将能够更加深入地理解计算机的工作原理,掌握常用软件的使用方法,为未来的学术或职业生涯打下坚实的基础

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值