[习题33]链表算法:冒泡排序、归并排序(单元测试)

使用教材

《“笨办法” 学C语言(Learn C The Hard Way)》
https://www.jianshu.com/p/b0631208a794

  • 完整源码 : liblcthw

https://github.com/zedshaw/liblcthw

作者原话

链表用于排序时很糟糕的,如果必须要排序,我们有别的更好的数据结构可用。之所以要将这两种算法, 是因为使用链表实现它们略微有点儿难度,而且还可以让你思考如何更加有效地进行链表操作。

工作顺序

首先,布置文件 list_algos.hlist_algos.clist_algos_tests.c

  • 1、查看文件结构,注意三个新增文件的位置
liblcthw$ ls -R
.:
bin  LICENSE  Makefile  README.md  src  tests

./bin:

./src:
lcthw

./src/lcthw:
dbg.h  list_algos.c  list_algos.h  list.c  list.h

./tests:
list_algos_tests.c  list_tests.c  minunit.h  runtests.sh

  • 2、运行 make 命令,warning不用在意,使编译通过
  • 3、再次查看文件结构 ls -R

然后 ,参考书上提供的步骤

[1] 打开 wiki 的页面,例如:冒泡排序(bubble sort)
[2] 阅读算法描述,观察图例
[3] 在纸上画出大致算法排序过程
[4] 回到wiki页面,复制、粘贴 “伪代码”(非C代码)到`list_algos.c`的冒泡函数里
[5] 把 伪代码 翻译成 C代码
[6] 使用单元测试来保证函数正常工作
[7] 重复步骤[5]~[6] 直到测试通过
[8] 添加更多测试,用来检测边缘情况,例如:空链表、已经排序过的链表等
[9] 实在做不出来可以“作弊”,看liblcthw库里的代码

排序算法

  • 冒泡排序

https://en.wikipedia.org/wiki/Bubble_sort

  • 归并排序

https://en.wikipedia.org/wiki/Merge_sort

输出结果

anno-m:~/Desktop/liblcthw$ make
cc -g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG  -fPIC   -c -o src/lcthw/list_algos.o src/lcthw/list_algos.c
cc -g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG  -fPIC   -c -o src/lcthw/list.o src/lcthw/list.c
ar rcs build/liblcthw.a src/lcthw/list_algos.o src/lcthw/list.o
ranlib build/liblcthw.a
cc -shared -o build/liblcthw.so src/lcthw/list_algos.o src/lcthw/list.o
cc -g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG     tests/list_algos_tests.c  -ldl build/liblcthw.a -o tests/list_algos_tests

cc -g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG     tests/list_tests.c  -ldl build/liblcthw.a -o tests/list_tests

sh ./tests/runtests.sh
Running unit tests:
----
RUNNING: ./tests/list_algos_tests
ALL TESTS PASSED
Tests run: 2
tests/list_algos_tests PASS
----
RUNNING: ./tests/list_tests
ALL TESTS PASSED
Tests run: 6
tests/list_tests PASS

源码说明

1、对回调函数的运用

  • 算法头文件 list_algos.h
typedef int (*List_compare) (const void *a, const void *b);
  • 算法实现文件 list_algos.c
int List_bubble_sort(List * list, List_compare cmp)
{
  // . . . 
      if (cmp(cur->value, cur->next->value) > 0) {
 // . . .
}
  • 单元测试文件 list_algos_tests.c
char *test_bubble_sort()
{
// . . . 
    int rc = List_bubble_sort(words, (List_compare) strcmp);
// . . .
}
  • 这样一来,通过在单元测试里写上strcmp,算法实现里就会解读成strcmp(cur->value, cur->next->value)

strcmp

  • 定义于头文件
  • int strcmp( const char *lhs, const char *rhs );

返回值
若字典序中 lhs 先出现于 rhs 则为负值。
若 lhs 与 rhs 比较相等则为零。
若字典序中 lhs 后出现于 rhs 则为正值。

2、如何实现结点互换?

  • 直接交换结点的value,而不去更改结点的prev以及next链接;
/*****    list_algos.c    *****/
inline void ListNode_swap(ListNode * a, ListNode * b)
{
    void *temp = a->value;
    a->value = b->value;
    b->value = temp;
}
/*****     list.h    *****/
typedef struct ListNode {
    struct ListNode *next;
    struct ListNode *prev;
    void *value;
} ListNode;

你可能感兴趣的:([习题33]链表算法:冒泡排序、归并排序(单元测试))