TDD实践:Go语言快排算法实现

TDD实践:Go语言快排算法实现


包结构介绍

  在学习Learn Go WIth Tests的过程中,我在$GOPATHsrc下创建了项目learn-go-with-tests,本小节实现快排算法,所以关注点在下图的红框中。

在这里插入图片描述
  需要注意的是,即便我们按照TDD流程开发算法,我们也要注意qsort.go文件内至少声明包package quicksort。随后我们开始进行下面的TDD流程。


先写测试

  编写如下测试:

// qsort_test.go
package quicksort

import "testing"

func TestQsort(t *testing.T) {
	var got = [8]int{1, 8, 2, 4, 3, 7, 5, 6};
	
	Qsort(got[:]);
	exp := [8]int{1, 2, 3, 4, 5, 6, 7, 8};

	if cmp(got[:], exp[:]) != true {
		t.Errorf("expected %v but got %v", exp, got);
	}
}

func cmp(a []int, b []int) bool {
	if len(a) != len(b) {
		return false;
	}
	for i := 0; i < len(a); i++ {
		if a[i] != b[i] {
			return false;
		}
	}
	return true;
}

尝试运行测试

  执行go test得到意料之中的报错信息:

在这里插入图片描述

先使用最少的代码来让失败的测试先跑起来

  现在只需让代码可编译,这样就可以检查测试用例能否通过。我们在qsort.go文件中定义Qsort函数:

// qsort.go
package quicksort

func Qsort(arr []int) {

}

  再次执行go test命令,我们发现编译已经成功,但如意料之中测试失败:

在这里插入图片描述

把代码补充完整,使得它能够通过测试

  将目光投向Qsort函数,我们将其补充完整。

package quicksort

func Qsort(arr []int) {
	qsortHelper(arr, 0, len(arr) - 1);
}

// sort elements in arr[low, high]
func qsortHelper(arr []int, low int, high int) {
	if low > high {
		return
	}
	tmp := arr[low];
	i := low;
	j := high;

	for i != j {
		for arr[j] >= tmp && j > i {
			j--;
		}
		for arr[i] <= tmp && j > i {
			i++;
		}
		if j > i {
			t := arr[i];
			arr[i] = arr[j];
			arr[j] = t;
		}
	}
	arr[low] = arr[i];
	arr[i] = tmp;
	qsortHelper(arr[:], low, i - 1);
	qsortHelper(arr[:], i + 1, high);
}

  我们再次测试,这一次执行go test -v,参数-v用于输出测试的详细信息:

在这里插入图片描述
  可以看到,我们通过了测试。


重构

  我们对helper进行重构,主要体现在变量交换上,我们可以避免临时变量的使用。比如上面交换arr[i]arr[j]时,我们可以利用Go语言多变量赋值的操作arr[i], arr[j] = arr[j], arr[i];。其他小改动在如下代码中给出。

// qsort.go
package quicksort

func Qsort(arr []int) {
	qsortHelper(arr, 0, len(arr) - 1);
}

// sort elements in arr[low, high]
func qsortHelper(arr []int, low, high int) { // 参数易读
	if low > high {
		return
	}
	tmp := arr[low];
	var i, j = low, high; // 赋值易读
	for i != j {
		for arr[j] >= tmp && j > i {
			j--;
		}
		for arr[i] <= tmp && j > i {
			i++;
		}
		if j > i {
			arr[i], arr[j] = arr[j], arr[i]; // 交换不需要临时变量
		}
	}
	arr[low] = arr[i];
	arr[i] = tmp;
	qsortHelper(arr[:], low, i - 1);
	qsortHelper(arr[:], i + 1, high);
}

基准测试

  编写基准测试:

// qsort_test.go
func BenchmarkRepeat(b *testing.B) {
    for i := 0; i < b.N; i++ {
        arr := [8]int{8, 6, 7, 1, 3, 4, 2, 5};
        Qsort(arr[:]);
    }
}  

执行go test -bench=.命令执行基准测试,可以得到:

在这里插入图片描述
结果说明执行一次快排函数执行了134 ns,函数一共执行了20487184次。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CharlesKai

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值