基础链表练习

基础链表练习


实现一个字符串链表,每插入一个字符串,链表会对其进行按字典进行排序(不区分大小写,如a在aa前,aa在b前等),重复插入的字符串自动忽略,通过索引号可以获取到对应位置上的字符串。


新工作开始。很久很久没写程序了,一开始发蒙,后来看了很多资料才找回了点感觉。感觉编程这东西就像弹琴,不练就生疏了,重新捡起来还要找感觉。


这个算是重启编程大道的第一个程序,写的不好,很多缺陷。


#include "list.h"
#include 
   
   
    
    
#include 
    
    
     
     

/**
 * 主程序
 */
int
main(int argc, char *argv[])
{
	pstLIST list = NULL;
	
    int i;
    char str[512];

	list = LIST_create();
	
	if(NULL != list)
	{
		char text[512];

		list->insert(list, "abc");
		list->insert(list, "bac");
        list->insert(list, "cba");

        printf("len is: %d\n", list->length(list));	//节点个数
		list->dump(list);	//打印出链表

        printf("输入查找序号:");
        scanf("%d", &i);
        list->lookup(list, i, text, sizeof(text));
        printf("位置%d的字符串为: %s\n", i,text);

        printf("输入要删除的字符串:");
        scanf("%s",str);
        list->remove(list, str);

        printf("now len is: %d\n", list->length(list));
		list->dump(list);

        LIST_release(&list);
	}
	return 0;
}
#include 
     
     
      
      
#include 
      
      
       
       

#ifndef PRACTICE_LIST_H_
#define PRACTICE_LIST_H_
#if defined(__cplusplus) & __cplusplus
extern "C" {
#endif
#define ssize_t int	///
       
       <定义类型 ** * @brief 链表节点数据结构 这是一个创建链表节点的数据结构 示例: @verbatim pstlist_node ptemp="NULL;" @endverbatim typedef struct taglist_node { char *data;> 
        <数据域:存储节点数据 struct taglist_node *next;> 
         <指针域:指向下一个节点 }stlist_node, *pstlist_node; ** * @brief 链表数据结构 这是一个链表数据结构 示例: @verbatim pstlist list @endverbatim typedef struct taglist { 向链表插入一条字符串数据 @param 要插入节点的链表 str 插入链表节点的内容 @return 成功返回0;\n重复插入返回0;\n失败返回-1。\n list->
           insert(list, "abc"); @endverbatim */ int (*insert)(struct tagLIST *list, const char *str); /** * 从链表中移除一条指定的字符串数据。 * @param list 要删除节点的链表 * @param str 要删除的内容 * @return 移除成功返回0,\n否则返回-1。\n * 示例: * @verbatim list->remove(list, str); @endverbatim */ int (*remove)(struct tagLIST *list, const char *str); /** * 返回链表的长度。 * @param list 要计算长度的链表 * @return 返回长度。\n * 示例: * @verbatim printf("now len is: %d\n", list->length(list)); @endverbatim */ ssize_t (*length)(struct tagLIST *list); /** * 按序号查找到该序号上的字符串。 * @param list 要查找的目标链表 * @param id 要查找的目标序号 * @param stack 查找成功后返回的字符串 * @param stacklen 返回的字符串的长度 * @return 若对应序号上有字符串则把字符串拷贝到缓冲长度为stacklen的stack的缓冲中并返回字符串的长度,\n * 否则返回-1。\n * 示例: * @verbatim list->lookup(list, i, text, sizeof(text)); @endverbatim */ ssize_t (*lookup)(struct tagLIST *list, int id, char *stack, size_t stacklen); /** * 按顺序打印链表中的字符串数据。 * @param list 要打印的目标链表 * @return 无。\n * 示例: * @verbatim list->dump(list); @endverbatim */ void (*dump)(struct tagLIST *list); /** * 取得尾节点,成功返回尾节点指针。 * @param list 目标链表 * @return 若成功则返回尾节点;\n否则返回-1。\n * 示例: * @verbatim pend = list->pend(list); @endverbatim */ struct tagLIST_NODE * (*pend)(struct tagLIST *list); struct tagLIST_NODE *next; /// 
          <定义一个next指针 }stlist, *pstlist; ** * 创建链表。 @retval 链表句柄 创建成功。 null 创建失败。 extern pstlist list_create(); 释放链表。 @param list 待释放链表。 @return 无。 void list_release(pstlist *list); #if defined(__cplusplus) & __cplusplus } #endif #include "list.h" 
            #include 
           
             /** * 向链表插入一条字符串数据 * @param list 要插入节点的链表 * @param str 插入链表节点的内容 * @return 成功返回0;\n重复插入返回0;\n失败返回-1。\n * 示例: * @verbatim list->insert(list, "abc"); @endverbatim */ static int list_insert(struct tagLIST *const list, const char *str) { char *dup_str; pstLIST_NODE ptemp = NULL; //临时节点 pstLIST_NODE pend = NULL; //尾节点 if (!str) //判断字符串是否为空 { return -1; } pend = list->pend(list); //得尾节点 ptemp = (pstLIST_NODE)calloc(1, sizeof(stLIST_NODE)); //为临时节点分配空间 if (!ptemp) //看临时节点分配是否有效 { return -1; } dup_str =strdup(str); ptemp->data = dup_str; //存储新字符串 if (NULL == pend) //若尾节点为空,临时节点插入头节点后,否则插入尾节点后 { list->next = ptemp; } else { pend->next = ptemp; } return 0; } /** * 从链表中移除一条指定的字符串数据。 * @param list 要删除节点的链表 * @param str 要删除的内容 * @return 移除成功返回0,\n否则返回-1。\n * 示例: * @verbatim list->remove(list, str); @endverbatim */ static int list_remove(struct tagLIST *const list, const char *str) { // TODO pstLIST_NODE ptemp = NULL; //创建一个临时节点 pstLIST_NODE ptemp2 = NULL; //创建一个临时节点2,指向临时节点的前一个节点 if (NULL == str) //判断字符串有效性 { return -1; } if (NULL != list->next) { ptemp = list->next; //链表非空,临时节点指向第一个节点 if (0 == strcmp(ptemp->data, str)) //如果查找到的就是第一个节点,删除第一个节点 { //判断链表是否存在第二个节点 if(ptemp->next) // 存在第二个节点 { list->next = ptemp->next; // 头结点直接指向第二个节点 } else { list->next = NULL; // 不存在第二个节点,头结点指向NULL } free(ptemp); // 释放第一个节点占用的空间 return 0; // 任务已完成,返回0到调用处 } ptemp2 = ptemp; ptemp = ptemp->next; //临时节点2指向临时节点的前一个节点 while (ptemp) { if (0 == strcmp(ptemp->data, str)) //查找符合的字符串 { if (NULL == ptemp->next) //如果目标节点是尾节点,则删除尾节点 { ptemp2->next = NULL; } ptemp2->next = ptemp->next; free(ptemp); return 0; } else { ptemp2 = ptemp; ptemp = ptemp->next; } } } return -1; //匹配失败返回 } /** * 返回链表的长度。 * @param list 要计算长度的链表 * @return 返回长度。\n * 示例: * @verbatim printf("now len is: %d\n", list->length(list)); @endverbatim */ static ssize_t list_length(struct tagLIST *const list) { // TODO pstLIST_NODE ptemp = NULL; //定义一个临时节点 int len; //链表长度 if (list->next) //链表非空 { len = 1; //链表初始长度1 ptemp = list->next; //临时节点指向头节点的下一节点 while (NULL != ptemp->next) { ptemp = ptemp->next; //遍历整个链表,统计出节点个数 len++; } } return ((ssize_t)len); //返回长度 } /** * 按序号查找到该序号上的字符串。 * @param list 要查找的目标链表 * @param id 要查找的目标序号 * @param stack 查找成功后返回的字符串 * @param stacklen 返回的字符串的长度 * @return 若对应需要上有字符串则把字符串拷贝到缓冲长度为stacklen的stack的缓冲中并返回字符串的长度,\n * 否则返回-1。\n * 示例: * @verbatim list->lookup(list, i, text, sizeof(text)); @endverbatim */ static ssize_t list_lookup(struct tagLIST *const list, int id, char *stack, size_t stacklen) { int l = 0; int i = 0; pstLIST_NODE ptemp = NULL; //临时节点 l = list->length(list); ptemp = list->next; if (id <= l) //id没有超出链表长度 { for (i = 1; i < id; i++) { ptemp = ptemp->next; //遍历找出id对应的节点 } //复制字符串到缓冲区 for (i = 0; i < stacklen; i++) { if (ptemp->data[i]) //判断字符串是否结束 { stack[i] = ptemp->data[i]; } else { stack[i] = 0; //字符串结束 return ((ssize_t)i); } } } return ((ssize_t)-1); //id超出链表长度 } /** * 按顺序打印链表中的字符串数据。 * @param list 要打印的目标链表 * @return 无。\n * 示例: * @verbatim list->dump(list); @endverbatim */ static void list_dump(struct tagLIST *const list) { // TODO pstLIST_NODE ptemp = NULL; //定义一个临时节点 //链表非空 if (list->next) { ptemp = list->next; //临时节点指向第一个节点 //遍历打印所有节点字符串 while (ptemp) { printf("%s\n", ptemp->data); ptemp = ptemp->next; } } else { printf("链表是空的\n"); } } /** * 取得尾节点,成功返回尾节点指针。 * @param list 目标链表 * @return 若成功则返回尾节点;\n否则返回-1。\n * 示例: * @verbatim pend = list->pend(list); @endverbatim */ static struct tagLIST_NODE * list_pend(struct tagLIST *const list) { // TODO: 尾节点指针 pstLIST_NODE pend = NULL; // 尾节点指针 if(NULL != list->next) { pend = list->next; // 初始化尾节点 // TODO: 循环判断是否已经处于尾节点处 while(NULL != pend->next) { pend = pend->next; // 继续遍历 } return pend; // 链表不为空,返回尾节点 } else { return 0; // 链表为空,返回0 } } pstLIST LIST_create() { pstLIST list = (pstLIST)calloc(sizeof(stLIST), 1); //为头结点分配空间 //分配空间失败返回NULL if(!list) { return NULL; } else { // 接口 list->insert = list_insert; list->remove = list_remove; list->length = list_length; list->lookup = list_lookup; list->dump = list_dump; list->pend = list_pend; list->next = NULL; return list; } } void LIST_release(pstLIST *list) { pstLIST_NODE ptemp = NULL; //创建一个临时节点指针 //判断链表是否空 if(NULL == (*list)) { return; } ptemp = (*list)->next; //临时节点指向第一个节点 //遍历释放每一个节点空间 while (ptemp) { (*list)->next = ptemp->next; //依次删除排头的节点 free(ptemp); ptemp = (*list)->next; } free(*list); //释放链表空间 (*list) = NULL; } 
            
           
          
         
       
      
      
     
     
    
    
   
   

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值