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

使用教材

完整源码 : liblcthw

作者原话

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

工作顺序

首先,布置文件 list_algos.h、list_algos.c 、list_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库里的代码

排序算法

冒泡排序

归并排序

输出结果

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;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值