当前位置: 首页 > news >正文

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语言数据结构之单向链表&#xff08;SingleList&#xff09; 自定义结构体数据类型SListNode表示单向链表的节点&#xff0c;成员包括一个无类型的data用来存贮数据和一个SListNode本身类型的指针next&#xff0c;指向下一个节点。围绕SListNode写一系列函数以slist_开头实现…...

【银河麒麟高级服务器操作系统实例】金融行业TCP连接数猛增场景的系统优化

了解更多银河麒麟操作系统全新产品&#xff0c;请点击访问 麒麟软件产品专区&#xff1a;https://product.kylinos.cn 开发者专区&#xff1a;https://developer.kylinos.cn 文档中心&#xff1a;https://documentkylinos.cn 服务器环境以及配置 物理机/虚拟机/云/容器 物理…...

详解Java的类文件结构(.class文件的结构)

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

爆肝整理14天!AI工具宝藏合集

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

高效库存管理:金蝶云星空与管易云的盘亏单对接方案

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

小鹏汽车股价分析:看涨信号已出现,技术指标显示还有40%的上涨空间

猛兽财经核心观点&#xff1a; &#xff08;1&#xff09;小鹏汽车的股价过去几天有所回落。 &#xff08;2&#xff09;随着需求的上升&#xff0c;该公司的业务发展的还算不错。 &#xff08;3&#xff09;猛兽财经对小鹏汽车股价的技术分析&#xff1a;多头已经将目标指向15…...

c语言指针详解2

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

Chrome DevTools 二: Performance 性能面板

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

渠道推广如何识别与防止虚假流量?

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

Keil C51 9.61__官网“最新版“下载、安装及相关提示( 保姆级教程, 安装过程详解, 附安装包 )

前言 Keil 5常用的分两个版本&#xff0c;C51 和 MDK。C51用于编译8051内核的单片机程序&#xff0c;譬如AT89C51、STC89C51、STC98C52等。MDK用于编译STM32、GD32等ARM32位内核单片机程序。 ‌Keil C51‌是由Keil Software Company开发的&#xff0c;专门用于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…...

我希望,你把篮球和鸡联系起来想一想。。。

“我希望&#xff0c;你把篮球和鸡联系起来想一想。” “篮球和鸡?” “我有一个好点子…” 目录 创建页面页面准备实现基础样式实现鸡的跑马灯 篮球弹跳实现篮球击出检查是否击中鸡并计算得分实现看一眼就爆炸效果 总结技术点完整代码 创建页面 页面准备 首先开始万恶的第一…...

STM32 ADC介绍

文章目录 STM32 ADC介绍一、ADC的基本概念二、STM32 ADC的主要特点高分辨率&#xff1a;多通道输入&#xff1a;多种工作模式&#xff1a;内置温度传感器和参考电压&#xff1a; 三、ADC的工作原理采样阶段&#xff1a;转换阶段&#xff1a;数据存储&#xff1a; 四、ADC的配置…...

JavaWeb合集12-Redis

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

【C++】在Windows中使用Boost库——实现TCP、UDP通信

目录 一、编译Boost库 二、TCP服务端 三、TCP客户端 四、UDP连接 一、编译Boost库 1. 先去官网下载Boost库源码 2. 点击下载最新的版本 下载Windows环境的压缩包&#xff0c;然后解压 3. 在解压后的目录路径下找到“bootstrap.bat” 打开控制台&#xff0c;在“bootstrap.…...

怎么提取pdf的某一页?批量提取pdf的某一页的简单方法

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

Github优质项目推荐(第八期)

文章目录 Github优质项目推荐 - 第八期一、【manim】&#xff0c;66.5k stars - 创建数学动画的 Python 框架二、【siyuan】&#xff0c;19.5k stars - 个人知识管理软件三、 【GetQzonehistory】&#xff0c;1.3k stars - 获取QQ空间发布的历史说说四、【SecLists】&#xff0…...

快读快写模板

原理 众所周知&#xff0c;在c中&#xff0c;用putchar和getchar输入输出字符的速度是很快的&#xff0c;因此&#xff0c;我们可以考虑把数字转化为字符&#xff0c;按位输出&#xff1b;把字符读入后转化为数字的每一位。 该快读快写可以实现对所有整数类型的输入。 templ…...

make_blobs函数

make_blobs 是 scikit-learn 库中用于生成聚类&#xff08;或分类&#xff09;数据集的函数。它通常用于生成多个高斯分布的簇状数据&#xff0c;以便进行分类或聚类算法的测试和验证。make_blobs 非常灵活&#xff0c;可以控制簇的数量、样本数量、每个簇的标准差、中心点等参…...

特斯拉Optimus:展望智能生活新篇章

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

基于Leaflet和SpringBoot的全球国家综合检索WebGIS可视化

目录 前言 一、Java后台程序设计 1、业务层设计 2、控制层设计 二、WebGIS可视化实现 1、侧边栏展示 2、空间边界信息展示 三、标注成果展示 1、面积最大的国家 2、国土面积最小的国家 3、海拔最低的国家 4、最大的群岛国家 四、总结 前言 在前面的博文中&#xff…...

【Linux】/usr/share目录

在Linux和类Unix操作系统中&#xff0c;/usr/share 目录是一个用于存放共享数据文件的目录。这个目录遵循Filesystem Hierarchy Standard (FHS)&#xff0c;它定义了Linux系统中文件和目录的组织结构。/usr 代表 “user”&#xff0c;而 share 表示这些文件可以被系统上的多个用…...

Java中如何应用序列化 serialVersionUID 版本号呢?

文章目录 示例1&#xff1a;没有 serialVersionUID 的类输出结果&#xff1a;示例2&#xff1a;类修改后未定义 serialVersionUID可能出现的问题&#xff1a;示例3&#xff1a;显式定义 serialVersionUID总结最佳实践推荐阅读文章 为了更好地理解 serialVersionUID 的使用&…...

面部识别技术:AI 如何识别人脸

在科技飞速发展的今天&#xff0c;面部识别技术已经广泛应用于各个领域&#xff0c;从手机解锁到安防监控&#xff0c;从金融支付到门禁系统&#xff0c;面部识别技术正在改变着我们的生活方式。那么&#xff0c;AI 究竟是如何识别人脸的呢&#xff1f;让我们一起来揭开面部识别…...

全面解析文档对象模型(DOM)及其操作(DOM的概念与结构、操作DOM节点、描述DOM树的形成过程、用DOMParser解析字符串为DOM对象)

1. 引言 文档对象模型&#xff08;DOM&#xff09;是Web开发中的核心概念&#xff0c;它提供了一种结构化的方法来表示和操作HTML和XML文档。通过DOM&#xff0c;开发者可以动态地访问和更新文档的内容、结构和样式。本文将深入探讨DOM的概念与结构、操作DOM节点的方法、DOM树…...

字符串使用方法:

字符串: -- 拼接字符串 SELECT CONCAT(糯米,啊啊啊撒,删掉); -- 字符长度 SELECT LENGTH(asssssssggg); -- 转大写 SELECT UPPER(asdf); -- 转小写 SELECT LOWER(ASDFG); -- 去除左边空格 SELECT LTRIM( aaaasdrf ); -- 去除右边空格 SELECT RTRIM( aaaasdff ); -- 去除两端…...

想让前后端交互更轻松?alovajs了解一下?

作为一个前端开发者&#xff0c;我最近发现了一个超赞的请求库 alovajs&#xff0c;它真的让我眼前一亮&#xff01;说实话&#xff0c;我感觉自己找到了前端开发的新大陆。大家知道&#xff0c;在前端开发中&#xff0c;处理 Client-Server 交互一直是个老大难的问题&#xff…...

E/MicroMsg.SDK.WXMediaMessage:checkArgs fail,thumbData is invalid 图片资源太大导致分享失败

1、微信分享报&#xff1a; 2、这个问题是因为图片太大导致&#xff1a; WXWebpageObject webpage new WXWebpageObject();webpage.webpageUrl qrCodeUrl;//用 WXWebpageObject 对象初始化一个 WXMediaMessage 对象WXMediaMessage msg new WXMediaMessage(webpage);msg.tit…...

No.21 笔记 | WEB安全 - 任意文件绕过详解 part 3

&#xff08;一&#xff09;空格绕过 原理 Windows系统将文件名中的空格视为空&#xff0c;但程序检测代码无法自动删除空格&#xff0c;使攻击者可借此绕过黑名单限制。基于黑名单验证的代码分析 代码未对上传文件的文件名进行去空格处理&#xff0c;存在安全隐患。相关代码逻…...

咸鱼自动发货 免费无需授权

下载&#xff1a;&#xff08;两个都可以下&#xff0c;自己选择&#xff09; https://pan.quark.cn/s/1e3039e322ad https://pan.xunlei.com/s/VO9ww89ZNkEg_Fq1wRr-fk9ZA1?pwd8x9s# 不是闲管家 闲鱼自动发货&#xff08;PC端&#xff09; 暂不支持密&#xff0c;免费使…...

邢台做网站多少钱/自己建网站流程

在 asyncData 有错误的时候会出现这个错误,这个可以自定义吗? 可以, 完全自定义错误页面 不知道是不是官方文档故意不添加此方法&#xff0c;还是他们完全忘记了有这么一回事&#xff0c;此方法是通过 issues 找到的。 项目目录新增 app/views/error.html&#xff0c; app …...

猎头网站怎么做/seo是什么专业的课程

sqlSession.selectList("xxx",null,rowBounds);转载于:https://www.cnblogs.com/orziii/p/7406449.html...

记事本做网站怎么加背景图/网站百度seo关键词优化

今天给大家筛选了8本侧重基础的ABAQUS书籍&#xff0c;大家可根据自己的学习需求阅读练习。ABAQUS6.6基础教程与实例详解作者&#xff1a;刘展出版社&#xff1a;中国水利水电出版社简介&#xff1a;本书全面系统地介绍了ABAQUS6.6的使用。分为两部分&#xff0c;第1部分为ABAQ…...

做网站联系我们在那个板块里面/app推广方案策划

前几天初步解决了困扰许久的socket10053的问题。 现象如下&#xff1a;windows下开发多线程socket通信的系统(采用事件选择WSAEventSelect的方式)&#xff0c;在高并发的情况下send及recv时经常出错&#xff08;有时是收到错误码不为0的FD_CLOSE事件&#xff09;&#xff0c;错…...

做美食下载什么网站/如何做网站平台

请编写一个通用工具类&#xff0c;该类具有如下功能&#xff1a; 1&#xff09;判断一个字符串是否是邮箱地址 2&#xff09;判断一个字符串是否是手机号码 3&#xff09;判断一个字符串是否是电话号码 4&#xff09;判断一个字符串是否是IP地址 代码结构如下&#xff0c;请补充…...

淘宝几百块做网站还有其他费用吗/海外网络推广

文章来源http://hi.baidu.com/xc_jetguo/blog/item/b1cb502266a1f649935807fa.html 可以把普通的Java程序做成真正的exe,也就是单一个exe就可以在没有安装JVM的机器上运行。 这样的工具常见的有JET和gcj.前者是收费的&#xff0c;而且做出来的exe还是需要一堆dll。 推荐使用g…...