C语言数据结构之单向链表(SingleList)
C语言数据结构之单向链表(SingleList)
- 自定义结构体数据类型SListNode表示单向链表的节点,成员包括一个无类型的data用来存贮数据和一个SListNode本身类型的指针next,指向下一个节点。
- 围绕SListNode写一系列函数以slist_开头实现单向链表的各种功能,做一个简单的封装。
创建链表slist_node_new与释放链表slist_free
- 创建链表节点函数slist_node_new,带一个无类型的参数,做为节点的数据!
- 释放单向链表函数slist_free,参数单向链表节点,从此节点开始的节点都将被释放!
代码如下:
/* filename : slist.c */
#include <stdio.h>
#include <stdlib.h>/**/
typedef struct _SListNode SListNode;
struct _SListNode {void *data;SListNode *next;
};/**/
SListNode *
slist_node_new (void *data)
{SListNode *node = (SListNode*) malloc (sizeof(SListNode));node->data = data;node->next = NULL;return node;
}/**/
void
slist_free (SListNode *root)
{SListNode *tmp;while (root != NULL){tmp = root->next;free (root);root = tmp;}
}/**/
int
main (int argc, char *argv[])
{char *name = "Tomson";SListNode *root = slist_node_new (name);slist_free(root);return 0;
}
/* --[#|#]-- */
编译运行,达到预期,检测一下内存情况,结果如下:
songvm@ubuntu:~/works/xdn/loo$ gcc slist.c -o slist
songvm@ubuntu:~/works/xdn/loo$ ./slist
songvm@ubuntu:~/works/xdn/loo$ valgrind --leak-check=yes ./slist
==2046== Memcheck, a memory error detector
==2046== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==2046== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==2046== Command: ./slist
==2046==
==2046==
==2046== HEAP SUMMARY:
==2046== in use at exit: 0 bytes in 0 blocks
==2046== total heap usage: 1 allocs, 1 frees, 16 bytes allocated
==2046==
==2046== All heap blocks were freed -- no leaks are possible
==2046==
==2046== For counts of detected and suppressed errors, rerun with: -v
==2046== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
链表尾部追加append,链表头部追加prepend,链表逐项操作foreach
- 链表尾部追加函数 slist_append,参数为无类型指针
- 链表头部追加函数 slist_prepend,参数为无类型指针
- 链表逐项操作函数 slist_foreach,参数为函数指针MgFunc,需要自定义一个函数来操作逐个节点的数据
- 测试函数,向链表追加了四个字符串AAAA,BBBB,CCCC,DDDD,逐项操作显示链内容,然后向链表头部追加字符串EEEE,再逐项操作显示结果为EEEE,AAAA,BBBB,CCCC,DDDD
代码如下:
/* filename : slist.c */
#include <stdio.h>
#include <stdlib.h>/* define function pointer with a void* argument */
typedef void (*MgFunc) (void *data);/* define single list node datatype */
typedef struct _SListNode SListNode;
struct _SListNode {void *data;SListNode *next;
};/* create a new single list node */
SListNode *
slist_node_new (void *data)
{SListNode *node = (SListNode*) malloc (sizeof(SListNode));node->data = data;node->next = NULL;return node;
}/* free single list node from root to end */
void
slist_free (SListNode *root)
{SListNode *tmp;while (root != NULL){tmp = root->next;free (root);root = tmp;}
}/* append a new node at single list tail of head with data */
SListNode *
slist_append (SListNode *head, void *data)
{SListNode *tmp = head, *node = slist_node_new (data);while (tmp->next != NULL)tmp = tmp->next;tmp->next = node;return head;
}/* prev append a new node as head of single list head with data */
SListNode *
slist_preppend (SListNode *head, void *data)
{SListNode *node = slist_node_new (data);node->next = head;return node;
}/* foreach single list node run mgfunc from head to end */
void
slist_foreach (SListNode *head, MgFunc mgfunc)
{SListNode *tmp = head;while (tmp != NULL){mgfunc (tmp->data);tmp = tmp->next;}
}/* ------------------------------ *//* define function for MgFunc */
void
out_string (void *data)
{printf ("[%s], ", (char*)data);
}/* test slist append and preppend */
void
test_slist_append (void)
{char *txt[5] = {"AAAA", "BBBB", "CCCC", "DDDD", "EEEE"};SListNode *head = slist_node_new (txt[0]);head = slist_append (head, txt[1]);head = slist_append (head, txt[2]);head = slist_append (head, txt[3]);slist_foreach (head, out_string); printf ("\n");head = slist_preppend (head, txt[4]);slist_foreach (head, out_string); printf ("\n");slist_free(head);
}/**/
int
main (int argc, char *argv[])
{test_slist_append ();return 0;
}
/* --[#|#]-- */
编译运行,达到预期,检测内存分配释放情况,结果如下:
songvm@ubuntu:~/works/xdn/loo$ gcc slist.c -o slist
songvm@ubuntu:~/works/xdn/loo$ ./slist
[AAAA], [BBBB], [CCCC], [DDDD],
[EEEE], [AAAA], [BBBB], [CCCC], [DDDD],
songvm@ubuntu:~/works/xdn/loo$ valgrind --leak-check=yes ./slist
==2198== Memcheck, a memory error detector
==2198== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==2198== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==2198== Command: ./slist
==2198==
[AAAA], [BBBB], [CCCC], [DDDD],
[EEEE], [AAAA], [BBBB], [CCCC], [DDDD],
==2198==
==2198== HEAP SUMMARY:
==2198== in use at exit: 0 bytes in 0 blocks
==2198== total heap usage: 6 allocs, 6 frees, 1,104 bytes allocated
==2198==
==2198== All heap blocks were freed -- no leaks are possible
==2198==
==2198== For counts of detected and suppressed errors, rerun with: -v
==2198== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
链表连接concat,链表插入insert
- 链表连接函数slist_concat,参数为两个链表的头部节点,返回值为两个链表连接后的头部结点
- 链表插入函数slist_insert,参数为链表的位置索引和数据,带数据创建节点然后插入到指定的索引位置
代码如下:
/* concat single list sla and slb, return sla as head */
SListNode *
slist_concat (SListNode *sla, SListNode *slb)
{SListNode *tmp = sla;while (tmp->next != NULL)tmp = tmp->next;tmp->next = slb;return sla;
}/* insert a node into single list of head with data */
SListNode *
slist_insert (SListNode *head, int pos, void *data)
{int idx = 0;SListNode *tmp = head;while (tmp != NULL){if (idx == pos){SListNode *next, *node;node = slist_node_new (data);next = tmp->next;tmp->next = node;node->next = next;break;}tmp = tmp->next;idx = idx + 1;}return head;
}
- 测试函数test_slist_concat,创建两个链表lsa内容为:AAAA,BBBB,CCCC和lsb内容为:DDDD,EEEE,连接后链表内容为:AAAA,BBBB,CCCC,DDDD,EEEE
- 测试函数test_slist_insert,创建链表,依次向位置索引1和4插入字符串XXXX
代码如下:
/**/
void
test_slist_concat (void)
{char *txt[5] = {"AAAA", "BBBB", "CCCC", "DDDD", "EEEE"};SListNode *head, *sla, *slb;sla = slist_node_new (txt[0]);sla = slist_append (sla, txt[1]);sla = slist_append (sla, txt[2]);slb = slist_node_new (txt[3]);slb = slist_append (slb, txt[4]);slist_foreach (sla, out_string); printf ("\n");slist_foreach (slb, out_string); printf ("\n");head = slist_concat (sla, slb);slist_foreach (head, out_string); printf ("\n");slist_free (head);
}/**/
void
test_slist_insert (void)
{char *txt[5] = {"AAAA", "BBBB", "CCCC", "DDDD", "EEEE"};char *str = "XXXX";SListNode *head = slist_node_new (txt[0]);for (int i = 1; i < 5; i++)head = slist_append (head, txt[i]);slist_foreach (head, out_string); printf ("\n");head = slist_insert (head, 1, str);head = slist_insert (head, 4, str);slist_foreach (head, out_string); printf ("\n");slist_free (head);
}
编译运行,测试连接两个链表,结果如预期:
songvm@ubuntu:~/works/xdn/loo$ gcc slist.c -o slist
songvm@ubuntu:~/works/xdn/loo$ ./slist
[AAAA], [BBBB], [CCCC],
[DDDD], [EEEE],
[AAAA], [BBBB], [CCCC], [DDDD], [EEEE],
songvm@ubuntu:~/works/xdn/loo$
编译运行,测试向链表中插入数据,结果如预期:
songvm@ubuntu:~/works/xdn/loo$ gcc slist.c -o slist
songvm@ubuntu:~/works/xdn/loo$ ./slist
[AAAA], [BBBB], [CCCC], [DDDD], [EEEE],
[AAAA], [BBBB], [XXXX], [CCCC], [DDDD], [XXXX], [EEEE],
songvm@ubuntu:~/works/xdn/loo$
链表删除节点remove,链表删除头部节点remove_head,链表删除尾部节点remove_tail
- 删除节点函数slist_remove,参数为指定节点的索引值
- 删除头部节点函数slist_remove_head
- 删除尾部节点函数slist_remove_tail
代码如下:
/* remove a node in single list at nth */
SListNode *
slist_remove (SListNode *head, int nth)
{SListNode *tmp = head, *pn = head;int idx = 0;while (tmp->next != NULL){if (idx == nth){SListNode *node = tmp->next;free (tmp);if (idx == 0) return node;else pn->next = node;break;}pn = tmp;tmp = tmp->next;idx = idx + 1;}return head;
}/* remove the single list head node */
SListNode *
slist_remove_head (SListNode *sln)
{SListNode *tmp = sln->next;if (sln == NULL) return sln;free (sln);sln = tmp;return sln;
}/* remove the single list tail node */
SListNode *
slist_remove_tail (SListNode *sln)
{SListNode *tmp = sln, *pn;while (tmp->next != NULL){pn = tmp;tmp = tmp->next;}pn->next = NULL;free (tmp);return sln;
}
- 测试函数test_slist_remove,创建链表,删除索引值为1和2的节点
- 测试函数test_slist_remove_head_tail,创建链表,分别删除链表的头节点和尾节点
代码如下:
/**/
void
test_slist_remove (void)
{char *txt[5] = {"AAAA", "BBBB", "CCCC", "DDDD", "EEEE"};SListNode *head = slist_node_new (txt[0]);for (int i = 1; i < 5; i++)head = slist_append (head, txt[i]);slist_foreach (head, out_string); printf ("\n");head = slist_remove (head, 1);head = slist_remove (head, 2);slist_foreach (head, out_string); printf ("\n");slist_free (head);
}/**/
void
test_slist_remove_head_tail (void)
{char *txt[5] = {"AAAA", "BBBB", "CCCC", "DDDD", "EEEE"};SListNode *head = slist_node_new (txt[0]);for (int i = 1; i < 5; i++)head = slist_append (head, txt[i]);slist_foreach (head, out_string); printf ("\n");head = slist_remove_head (head);slist_foreach (head, out_string); printf ("\n");head = slist_remove_tail (head);slist_foreach (head, out_string); printf ("\n");slist_free (head);
}
编译运行,测试删除链表节点,顺利通过,结果如下:
songvm@ubuntu:~/works/xdn/loo$ gcc slist.c -o slist
songvm@ubuntu:~/works/xdn/loo$ ./slist
[AAAA], [BBBB], [CCCC], [DDDD], [EEEE],
[AAAA], [CCCC], [EEEE],
songvm@ubuntu:~/works/xdn/loo$
编译运行,测试删除链表头和链表尾,同时检查内存使用情况,达到目标,结果如下:
songvm@ubuntu:~/works/xdn/loo$ gcc slist.c -o slist
songvm@ubuntu:~/works/xdn/loo$ ./slist
[AAAA], [BBBB], [CCCC], [DDDD], [EEEE],
[BBBB], [CCCC], [DDDD], [EEEE],
[BBBB], [CCCC], [DDDD],
songvm@ubuntu:~/works/xdn/loo$ valgrind --leak-check=yes ./slist
==2786== Memcheck, a memory error detector
==2786== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==2786== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==2786== Command: ./slist
==2786==
[AAAA], [BBBB], [CCCC], [DDDD], [EEEE],
[BBBB], [CCCC], [DDDD], [EEEE],
[BBBB], [CCCC], [DDDD],
==2786==
==2786== HEAP SUMMARY:
==2786== in use at exit: 0 bytes in 0 blocks
==2786== total heap usage: 6 allocs, 6 frees, 1,104 bytes allocated
==2786==
==2786== All heap blocks were freed -- no leaks are possible
==2786==
==2786== For counts of detected and suppressed errors, rerun with: -v
==2786== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
songvm@ubuntu:~/works/xdn/loo$
链表倒转reverse
- 链表倒转函数slist_reverse,将链表的各节点倒转过来!!!
代码如下:
/* reverse the single list, head change to tail */
SListNode *
slist_reverse (SListNode *sln)
{SListNode *tmp = sln, *tail = NULL;while (tmp != NULL){SListNode *node = tmp;tmp = tmp->next;node->next = tail;tail = node;}return tail;
}
- 测试函数,创建链表内容为ABCDE,倒转后内容为EDCBA
代码如下:
/**/
void
test_slist_reverse (void)
{char *txt[5] = {"AAAA", "BBBB", "CCCC", "DDDD", "EEEE"};SListNode *tail, *head = slist_node_new (txt[0]);for (int i = 1; i < 5; i++)head = slist_append (head, txt[i]);slist_foreach (head, out_string); printf ("\n");tail = slist_reverse (head);slist_foreach (tail, out_string); printf ("\n");slist_free (tail);
}
编译运行,顺利通过,测试内存情况,结果如下:
songvm@ubuntu:~/works/xdn/loo$ gcc slist.c -o slist
songvm@ubuntu:~/works/xdn/loo$ ./slist
[AAAA], [BBBB], [CCCC], [DDDD], [EEEE],
[EEEE], [DDDD], [CCCC], [BBBB], [AAAA],
songvm@ubuntu:~/works/xdn/loo$ valgrind --leak-check=yes ./slist
==2831== Memcheck, a memory error detector
==2831== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==2831== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==2831== Command: ./slist
==2831==
[AAAA], [BBBB], [CCCC], [DDDD], [EEEE],
[EEEE], [DDDD], [CCCC], [BBBB], [AAAA],
==2831==
==2831== HEAP SUMMARY:
==2831== in use at exit: 0 bytes in 0 blocks
==2831== total heap usage: 6 allocs, 6 frees, 1,104 bytes allocated
==2831==
==2831== All heap blocks were freed -- no leaks are possible
==2831==
==2831== For counts of detected and suppressed errors, rerun with: -v
==2831== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
songvm@ubuntu:~/works/xdn/loo$
求链表长度length,取链表节点get_nth,取链表节点的数据get_nth_data
- 求链表长度slist_length
- 取链表节点slist_get_nth,参数nth为索引值
- 取链表节点的数据slist_get_nth_data,参数nth为索引值
代码如下:
/* get single list length */
int
slist_length (SListNode *sln)
{int len = 0;SListNode *tmp = sln;while (tmp != NULL){tmp = tmp->next;len = len + 1;}return len;
}/* get nth node from single list begin 0, if has not return NULL */
SListNode *
slist_nth (SListNode *sln, int nth)
{int idx = 0;SListNode *tmp = sln;while (tmp != NULL){if (idx == nth) return tmp;tmp = tmp->next;idx = idx + 1;}return NULL;
}/* get data of nth node from single list */
void *
slist_nth_data (SListNode *sln, int nth)
{int idx = 0;SListNode *tmp = sln;while (tmp != NULL){if (idx == nth) return tmp->data;tmp = tmp->next;idx = idx + 1;}return NULL;
}
- 测试函数,创建链表,长度为5,第2节点为CCCC,第3节点为DDDD
代码如下:
/* */
void
test_slist_length (void)
{char *txt[5] = {"AAAA", "BBBB", "CCCC", "DDDD", "EEEE"};SListNode *node, *head;head = slist_node_new (txt[0]);for (int i = 1; i < 5; i++)head = slist_append (head, txt[i]);slist_foreach (head, out_string); printf ("\n");printf ("Single list length is %d\n", slist_length(head));node = slist_nth (head, 2);printf ("Single list 2nd node data is [%s]\n", (char*)(node->data));printf ("Single list 3th node data is [%s]\n", (char*)slist_nth_data(head, 3));slist_free (head);
}
编译运行,顺利通过,达到预期,运行结果如下:
songvm@ubuntu:~/works/xdn/loo$ gcc slist.c -o slist
songvm@ubuntu:~/works/xdn/loo$ ./slist
[AAAA], [BBBB], [CCCC], [DDDD], [EEEE],
Single list length is 5
Single list 2nd node data is [CCCC]
Single list 3th node data is [DDDD]
songvm@ubuntu:~/works/xdn/loo$
判断链表是否为循环链表
- 循环锭表的特征为next节点指针指向头节点,这样在逐项操作时会造成死循环!!!
- 判断链表是否为循环链表函数slist_is_round,是返回1,否则返回0!!!
代码如下:
/* if single list is round return 1, else return 0 */
int
slist_is_round (SListNode *sln)
{SListNode *tmp = sln, *node = tmp;while (tmp != NULL){tmp = tmp->next;if (tmp == node) return 1;}return 0;
}
- 测试函数,创建链表,尾指针指向头节点,成为循环链表,查看函数slist_is_round返回值
代码如下:
/**/
void
test_slist_is_round (void)
{char *txt[5] = {"AAAA", "BBBB", "CCCC", "DDDD", "EEEE"};SListNode *head, *tail;head = slist_node_new (txt[0]);for (int i = 1; i < 5; i++)head = slist_append (head, txt[i]);tail = slist_nth (head, 4);tail->next = head; //link roundif (slist_is_round (head))printf ("Single list is round!\n");elseprintf ("Single list not round!\n");tail->next = NULL; //cut roundif (slist_is_round (head))printf ("Single list is round!\n");elseprintf ("Single list not round!\n");slist_free (head);
}
编译运行,顺利通过,达到预期!!!运行结果如下:
songvm@ubuntu:~/works/xdn/loo$ gcc slist.c -o slist
songvm@ubuntu:~/works/xdn/loo$ ./slist
Single list is round!
Single list not round!
songvm@ubuntu:~/works/xdn/loo$
完整代码如下:
/* filename : slist.c */
#include <stdio.h>
#include <stdlib.h>/* define function pointer with a void* argument */
typedef void (*MgFunc) (void *data);/* define single list node datatype */
typedef struct _SListNode SListNode;
struct _SListNode {void *data;SListNode *next;
};/* create a new single list node */
SListNode *
slist_node_new (void *data)
{SListNode *node = (SListNode*) malloc (sizeof(SListNode));node->data = data;node->next = NULL;return node;
}/* free single list node from root to end */
void
slist_free (SListNode *root)
{SListNode *tmp;while (root != NULL){tmp = root->next;free (root);root = tmp;}
}/* append a new node at single list tail of head with data */
SListNode *
slist_append (SListNode *head, void *data)
{SListNode *tmp = head, *node = slist_node_new (data);while (tmp->next != NULL)tmp = tmp->next;tmp->next = node;return head;
}/* prev append a new node as head of single list head with data */
SListNode *
slist_preppend (SListNode *head, void *data)
{SListNode *node = slist_node_new (data);node->next = head;return node;
}/* foreach single list node run mgfunc from head to end */
void
slist_foreach (SListNode *head, MgFunc mgfunc)
{SListNode *tmp = head;while (tmp != NULL){mgfunc (tmp->data);tmp = tmp->next;}
}/* concat single list sla and slb, return sla as head */
SListNode *
slist_concat (SListNode *sla, SListNode *slb)
{SListNode *tmp = sla;while (tmp->next != NULL)tmp = tmp->next;tmp->next = slb;return sla;
}/* insert a node into single list of head with data */
SListNode *
slist_insert (SListNode *head, int pos, void *data)
{int idx = 0;SListNode *tmp = head;while (tmp != NULL){if (idx == pos){SListNode *next, *node;node = slist_node_new (data);next = tmp->next;tmp->next = node;node->next = next;break;}tmp = tmp->next;idx = idx + 1;}return head;
}/* remove a node in single list at nth */
SListNode *
slist_remove (SListNode *head, int nth)
{SListNode *tmp = head, *pn = head;int idx = 0;while (tmp->next != NULL){if (idx == nth){SListNode *node = tmp->next;free (tmp);if (idx == 0) return node;else pn->next = node;break;}pn = tmp;tmp = tmp->next;idx = idx + 1;}return head;
}/* remove the single list head node */
SListNode *
slist_remove_head (SListNode *sln)
{SListNode *tmp = sln->next;if (sln == NULL) return sln;free (sln);sln = tmp;return sln;
}/* remove the single list tail node */
SListNode *
slist_remove_tail (SListNode *sln)
{SListNode *tmp = sln, *pn;while (tmp->next != NULL){pn = tmp;tmp = tmp->next;}pn->next = NULL;free (tmp);return sln;
}/* reverse the single list, head change to tail */
SListNode *
slist_reverse (SListNode *sln)
{SListNode *tmp = sln, *tail = NULL;while (tmp != NULL){SListNode *node = tmp;tmp = tmp->next;node->next = tail;tail = node;}return tail;
}/* get single list length */
int
slist_length (SListNode *sln)
{int len = 0;SListNode *tmp = sln;while (tmp != NULL){tmp = tmp->next;len = len + 1;}return len;
}/* get nth node from single list begin 0, if has not return NULL */
SListNode *
slist_nth (SListNode *sln, int nth)
{int idx = 0;SListNode *tmp = sln;while (tmp != NULL){if (idx == nth) return tmp;tmp = tmp->next;idx = idx + 1;}return NULL;
}/* get data of nth node from single list */
void *
slist_nth_data (SListNode *sln, int nth)
{int idx = 0;SListNode *tmp = sln;while (tmp != NULL){if (idx == nth) return tmp->data;tmp = tmp->next;idx = idx + 1;}return NULL;
}/* if single list is round return 1, else return 0 */
int
slist_is_round (SListNode *sln)
{SListNode *tmp = sln, *node = tmp;while (tmp != NULL){tmp = tmp->next;if (tmp == node) return 1;}return 0;
}/* ------------------------------ *//* define function for MgFunc */
void
out_string (void *data)
{printf ("[%s], ", (char*)data);
}/* test slist append and preppend */
void
test_slist_append (void)
{char *txt[5] = {"AAAA", "BBBB", "CCCC", "DDDD", "EEEE"};SListNode *head = slist_node_new (txt[0]);head = slist_append (head, txt[1]);head = slist_append (head, txt[2]);head = slist_append (head, txt[3]);slist_foreach (head, out_string); printf ("\n");head = slist_preppend (head, txt[4]);slist_foreach (head, out_string); printf ("\n");slist_free(head);
}/**/
void
test_slist_concat (void)
{char *txt[5] = {"AAAA", "BBBB", "CCCC", "DDDD", "EEEE"};SListNode *head, *sla, *slb;sla = slist_node_new (txt[0]);sla = slist_append (sla, txt[1]);sla = slist_append (sla, txt[2]);slb = slist_node_new (txt[3]);slb = slist_append (slb, txt[4]);slist_foreach (sla, out_string); printf ("\n");slist_foreach (slb, out_string); printf ("\n");head = slist_concat (sla, slb);slist_foreach (head, out_string); printf ("\n");slist_free (head);
}/**/
void
test_slist_insert (void)
{char *txt[5] = {"AAAA", "BBBB", "CCCC", "DDDD", "EEEE"};char *str = "XXXX";SListNode *head = slist_node_new (txt[0]);for (int i = 1; i < 5; i++)head = slist_append (head, txt[i]);slist_foreach (head, out_string); printf ("\n");head = slist_insert (head, 1, str);head = slist_insert (head, 4, str);slist_foreach (head, out_string); printf ("\n");slist_free (head);
}/**/
void
test_slist_remove (void)
{char *txt[5] = {"AAAA", "BBBB", "CCCC", "DDDD", "EEEE"};SListNode *head = slist_node_new (txt[0]);for (int i = 1; i < 5; i++)head = slist_append (head, txt[i]);slist_foreach (head, out_string); printf ("\n");head = slist_remove (head, 1);head = slist_remove (head, 2);slist_foreach (head, out_string); printf ("\n");slist_free (head);
}/**/
void
test_slist_remove_head_tail (void)
{char *txt[5] = {"AAAA", "BBBB", "CCCC", "DDDD", "EEEE"};SListNode *head = slist_node_new (txt[0]);for (int i = 1; i < 5; i++)head = slist_append (head, txt[i]);slist_foreach (head, out_string); printf ("\n");head = slist_remove_head (head);slist_foreach (head, out_string); printf ("\n");head = slist_remove_tail (head);slist_foreach (head, out_string); printf ("\n");slist_free (head);
}/**/
void
test_slist_reverse (void)
{char *txt[5] = {"AAAA", "BBBB", "CCCC", "DDDD", "EEEE"};SListNode *tail, *head = slist_node_new (txt[0]);for (int i = 1; i < 5; i++)head = slist_append (head, txt[i]);slist_foreach (head, out_string); printf ("\n");tail = slist_reverse (head);slist_foreach (tail, out_string); printf ("\n");slist_free (tail);
}/* */
void
test_slist_length (void)
{char *txt[5] = {"AAAA", "BBBB", "CCCC", "DDDD", "EEEE"};SListNode *node, *head;head = slist_node_new (txt[0]);for (int i = 1; i < 5; i++)head = slist_append (head, txt[i]);slist_foreach (head, out_string); printf ("\n");printf ("Single list length is %d\n", slist_length(head));node = slist_nth (head, 2);printf ("Single list 2nd node data is [%s]\n", (char*)(node->data));printf ("Single list 3th node data is [%s]\n", (char*)slist_nth_data(head, 3));slist_free (head);
}/**/
void
test_slist_is_round (void)
{char *txt[5] = {"AAAA", "BBBB", "CCCC", "DDDD", "EEEE"};SListNode *head, *tail;head = slist_node_new (txt[0]);for (int i = 1; i < 5; i++)head = slist_append (head, txt[i]);tail = slist_nth (head, 4);tail->next = head; //link roundif (slist_is_round (head))printf ("Single list is round!\n");elseprintf ("Single list not round!\n");tail->next = NULL; //cut roundif (slist_is_round (head))printf ("Single list is round!\n");elseprintf ("Single list not round!\n");slist_free (head);
}/**/
int
main (int argc, char *argv[])
{//test_slist_append ();//test_slist_concat ();//test_slist_insert ();//test_slist_remove ();//test_slist_remove_head_tail ();//test_slist_reverse ();//test_slist_length ();test_slist_is_round ();return 0;
}
/* --[#|#]-- */
- 下一步,研究双向链表!!!
相关文章:
C语言数据结构之单向链表(SingleList)
C语言数据结构之单向链表(SingleList) 自定义结构体数据类型SListNode表示单向链表的节点,成员包括一个无类型的data用来存贮数据和一个SListNode本身类型的指针next,指向下一个节点。围绕SListNode写一系列函数以slist_开头实现…...

【银河麒麟高级服务器操作系统实例】金融行业TCP连接数猛增场景的系统优化
了解更多银河麒麟操作系统全新产品,请点击访问 麒麟软件产品专区:https://product.kylinos.cn 开发者专区:https://developer.kylinos.cn 文档中心:https://documentkylinos.cn 服务器环境以及配置 物理机/虚拟机/云/容器 物理…...

详解Java的类文件结构(.class文件的结构)
this_class 指向常量池中索引为 2 的 CONSTANT_Class_info。super_class 指向常量池中索引为 3 的 CONSTANT_Class_info。由于没有接口,所以 interfaces 的信息为空。 对应 class 文件中的位置如下图所示。 06、字段表 一个类中定义的字段会被存储在字段表&#x…...

爆肝整理14天!AI工具宝藏合集
随着AI技术的飞速发展,各类AI工具如雨后春笋般涌现。经过对上百款AI工具的深入探索与测试,我精心挑选出了一些功能强大的AI神器,这些工具将极大地降低自媒体创作的门槛。 🚀无论是撰写文案、剪辑视频、设计图文,还是处…...

高效库存管理:金蝶云星空与管易云的盘亏单对接方案
高效库存管理:金蝶云星空与管易云的盘亏单对接方案 金蝶云星空与管易云的盘亏单对接方案 在企业日常运营中,库存管理是至关重要的一环。为了实现高效、准确的库存盘点和数据同步,我们采用了轻易云数据集成平台,将金蝶云星空的数据…...

小鹏汽车股价分析:看涨信号已出现,技术指标显示还有40%的上涨空间
猛兽财经核心观点: (1)小鹏汽车的股价过去几天有所回落。 (2)随着需求的上升,该公司的业务发展的还算不错。 (3)猛兽财经对小鹏汽车股价的技术分析:多头已经将目标指向15…...

c语言指针详解2
c语言指针详解2 1.数组名理解 数组名其实是地址,是数组首元素的地址(详解1有提及) 我们可以根据打印来确认 我们发现数组名和数组⾸元素的地址打印出的结果⼀模⼀样,数组名就是数组⾸元素(第⼀个元素)的地址。 但是上述结论有…...

Chrome DevTools 二: Performance 性能面板
Chrome DevTools 第二篇 Performance 主要介绍performance在我们日常开发中所起到的作用,以及如何利用performance 面板进行性能分析和相关优化建议。 性能面板 Performance 记录和分析页面运行中的所有活动,是解决前端性能问题的重要工具。 1. 控制栏…...

渠道推广如何识别与防止虚假流量?
在当今竞争激烈的游戏市场中,渠道推广作为游戏开发商拓展用户基础、提升市场渗透率的关键手段,其重要性不言而喻。然而,随着市场的发展,渠道作弊问题日益严重,虚假流量、刷假量、拉人风险和违规代充等行为频繁出现&…...

Keil C51 9.61__官网“最新版“下载、安装及相关提示( 保姆级教程, 安装过程详解, 附安装包 )
前言 Keil 5常用的分两个版本,C51 和 MDK。C51用于编译8051内核的单片机程序,譬如AT89C51、STC89C51、STC98C52等。MDK用于编译STM32、GD32等ARM32位内核单片机程序。 Keil C51是由Keil Software Company开发的,专门用于8051微控制器的…...

二进制搭建 Kubernetes v1.20
k8s集群master01etcd集群节点1192.168.190.80 kube-apiserver kube-controller-manager kube-scheduler etcdk8s集群node01etcd集群节点2192.168.190.60kubelet kube-proxy docker etcdk8s集群node02etcd集群节点3192.168.190.70etcd VIP192.168.190.100 k8…...

我希望,你把篮球和鸡联系起来想一想。。。
“我希望,你把篮球和鸡联系起来想一想。” “篮球和鸡?” “我有一个好点子…” 目录 创建页面页面准备实现基础样式实现鸡的跑马灯 篮球弹跳实现篮球击出检查是否击中鸡并计算得分实现看一眼就爆炸效果 总结技术点完整代码 创建页面 页面准备 首先开始万恶的第一…...
STM32 ADC介绍
文章目录 STM32 ADC介绍一、ADC的基本概念二、STM32 ADC的主要特点高分辨率:多通道输入:多种工作模式:内置温度传感器和参考电压: 三、ADC的工作原理采样阶段:转换阶段:数据存储: 四、ADC的配置…...

JavaWeb合集12-Redis
十二、Redis 1、Redis 入门 Redis是一个基于内存的key-valule 结构数据库。 特点:基于内存存储,读写性能高 场景:适合存储热点数据(热点商品、资讯、新闻) Redis安装包分为Windows版和Linux版: Windows版 下载地址: https://gith…...

【C++】在Windows中使用Boost库——实现TCP、UDP通信
目录 一、编译Boost库 二、TCP服务端 三、TCP客户端 四、UDP连接 一、编译Boost库 1. 先去官网下载Boost库源码 2. 点击下载最新的版本 下载Windows环境的压缩包,然后解压 3. 在解压后的目录路径下找到“bootstrap.bat” 打开控制台,在“bootstrap.…...

怎么提取pdf的某一页?批量提取pdf的某一页的简单方法
怎么提取pdf的某一页?在日常工作与学习中,我们经常会遇到各式各样的PDF文件,它们以其良好的兼容性和稳定性,成为了信息传输和存储的首选格式。然而,在浩瀚的文档海洋中,有时某个PDF文件中的某一页内容尤为重…...

Github优质项目推荐(第八期)
文章目录 Github优质项目推荐 - 第八期一、【manim】,66.5k stars - 创建数学动画的 Python 框架二、【siyuan】,19.5k stars - 个人知识管理软件三、 【GetQzonehistory】,1.3k stars - 获取QQ空间发布的历史说说四、【SecLists】࿰…...
快读快写模板
原理 众所周知,在c中,用putchar和getchar输入输出字符的速度是很快的,因此,我们可以考虑把数字转化为字符,按位输出;把字符读入后转化为数字的每一位。 该快读快写可以实现对所有整数类型的输入。 templ…...
make_blobs函数
make_blobs 是 scikit-learn 库中用于生成聚类(或分类)数据集的函数。它通常用于生成多个高斯分布的簇状数据,以便进行分类或聚类算法的测试和验证。make_blobs 非常灵活,可以控制簇的数量、样本数量、每个簇的标准差、中心点等参…...

特斯拉Optimus:展望智能生活新篇章
近日,特斯拉举办了 "WE ROBOT" 发布会,发布会上描绘的未来社会愿景,让无数人为之向往。在这场吸引全球无数媒体的直播中,特斯拉 Optimus 人形机器人一出场就吸引了所有观众的关注。从多家媒体现场拍摄的视频可以看出来&…...

简易版抽奖活动的设计技术方案
1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...

376. Wiggle Subsequence
376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?
论文网址:pdf 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记,谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...

(二)原型模式
原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
随着新能源汽车的快速普及,充电桩作为核心配套设施,其安全性与可靠性备受关注。然而,在高温、高负荷运行环境下,充电桩的散热问题与消防安全隐患日益凸显,成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...

AI书签管理工具开发全记录(十九):嵌入资源处理
1.前言 📝 在上一篇文章中,我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源,方便后续将资源打包到一个可执行文件中。 2.embed介绍 🎯 Go 1.16 引入了革命性的 embed 包,彻底改变了静态资源管理的…...

保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek
文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama(有网络的电脑)2.2.3 安装Ollama(无网络的电脑)2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...

Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...