基础链表练习
新工作开始。很久很久没写程序了,一开始发蒙,后来看了很多资料才找回了点感觉。感觉编程这东西就像弹琴,不练就生疏了,重新捡起来还要找感觉。
这个算是重启编程大道的第一个程序,写的不好,很多缺陷。
#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; }