mirror of
https://github.com/golang/go
synced 2024-11-22 04:54:42 -07:00
additions to array container:
- added Slice, Cut, InsertArray, AppendArray - renamed Remove -> Delete (so we have: Insert, Delete, Cut) - more factoring of code - extra tests (could use some more) R=r,rsc DELTA=179 (127 added, 22 deleted, 30 changed) OCL=23648 CL=23685
This commit is contained in:
parent
712522a6d8
commit
cb659ece0e
@ -4,13 +4,47 @@
|
||||
|
||||
package array
|
||||
|
||||
type Element interface {
|
||||
type (
|
||||
Element interface {};
|
||||
Array struct {
|
||||
a []Element
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
func copy(dst, src []Element) {
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = src[i]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
type Array struct {
|
||||
// TODO do not export field
|
||||
a []Element
|
||||
// Insert n elements at position i.
|
||||
func expand(a []Element, i, n int) []Element {
|
||||
// make sure we have enough space
|
||||
len0 := len(a);
|
||||
len1 := len0 + n;
|
||||
if len1 < cap(a) {
|
||||
// enough space - just expand
|
||||
a = a[0 : len1]
|
||||
} else {
|
||||
// not enough space - double capacity
|
||||
capb := cap(a)*2;
|
||||
if capb < len1 {
|
||||
// still not enough - use required length
|
||||
capb = len1
|
||||
}
|
||||
// capb >= len1
|
||||
b := make([]Element, len1, capb);
|
||||
copy(b, a);
|
||||
a = b
|
||||
}
|
||||
|
||||
// make a hole
|
||||
for j := len0-1; j >= i ; j-- {
|
||||
a[j+n] = a[j]
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
|
||||
@ -61,38 +95,17 @@ func (p *Array) Last() Element {
|
||||
|
||||
|
||||
func (p *Array) Insert(i int, x Element) {
|
||||
a := p.a;
|
||||
n := len(a);
|
||||
|
||||
// grow array by doubling its capacity
|
||||
if n == cap(a) {
|
||||
b := make([]Element, 2*n);
|
||||
for j := n-1; j >= 0; j-- {
|
||||
b[j] = a[j];
|
||||
}
|
||||
a = b
|
||||
}
|
||||
|
||||
// make a hole
|
||||
a = a[0 : n+1];
|
||||
for j := n; j > i; j-- {
|
||||
a[j] = a[j-1]
|
||||
}
|
||||
|
||||
a[i] = x;
|
||||
p.a = a
|
||||
p.a = expand(p.a, i, 1);
|
||||
p.a[i] = x;
|
||||
}
|
||||
|
||||
|
||||
func (p *Array) Remove(i int) Element {
|
||||
func (p *Array) Delete(i int) Element {
|
||||
a := p.a;
|
||||
n := len(a);
|
||||
|
||||
x := a[i];
|
||||
for j := i+1; j < n; j++ {
|
||||
a[j-1] = a[j]
|
||||
}
|
||||
|
||||
copy(a[i : n-1], a[i+1 : n]);
|
||||
a[n-1] = nil; // support GC, nil out entry
|
||||
p.a = a[0 : n-1];
|
||||
|
||||
@ -100,13 +113,47 @@ func (p *Array) Remove(i int) Element {
|
||||
}
|
||||
|
||||
|
||||
func (p *Array) InsertArray(i int, x *Array) {
|
||||
p.a = expand(p.a, i, len(x.a));
|
||||
copy(p.a[i : i + len(x.a)], x.a);
|
||||
}
|
||||
|
||||
|
||||
func (p *Array) Cut(i, j int) {
|
||||
a := p.a;
|
||||
n := len(a);
|
||||
m := n - (j - i);
|
||||
|
||||
copy(a[i : m], a[j : n]);
|
||||
for k := m; k < n; k++ {
|
||||
a[k] = nil // support GC, nil out entries
|
||||
}
|
||||
|
||||
p.a = a[0 : m];
|
||||
}
|
||||
|
||||
|
||||
func (p *Array) Slice(i, j int) *Array {
|
||||
s := New(j - i); // will fail in Init() if j < j
|
||||
copy(s.a, p.a[i : j]);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
// Convenience wrappers
|
||||
|
||||
func (p *Array) Push(x Element) {
|
||||
p.Insert(len(p.a), x)
|
||||
}
|
||||
|
||||
|
||||
func (p *Array) Pop() Element {
|
||||
return p.Remove(len(p.a) - 1)
|
||||
return p.Delete(len(p.a) - 1)
|
||||
}
|
||||
|
||||
|
||||
func (p *Array) AppendArray(x *Array) {
|
||||
p.InsertArray(len(p.a), x);
|
||||
}
|
||||
|
||||
|
||||
|
@ -24,7 +24,7 @@ func TestNew(t *testing.T) {
|
||||
}
|
||||
|
||||
|
||||
func Val(i int) int {
|
||||
func val(i int) int {
|
||||
return i*991 - 1234
|
||||
}
|
||||
|
||||
@ -34,34 +34,34 @@ func TestAccess(t *testing.T) {
|
||||
var a array.Array;
|
||||
a.Init(n);
|
||||
for i := 0; i < n; i++ {
|
||||
a.Set(i, Val(i));
|
||||
a.Set(i, val(i));
|
||||
}
|
||||
for i := 0; i < n; i++ {
|
||||
if a.At(i).(int) != Val(i) { t.Error(i) }
|
||||
if a.At(i).(int) != val(i) { t.Error(i) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func TestInsertRemoveClear(t *testing.T) {
|
||||
func TestInsertDeleteClear(t *testing.T) {
|
||||
const n = 100;
|
||||
a := array.New(0);
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
if a.Len() != i { t.Errorf("A wrong len %d (expected %d)", a.Len(), i) }
|
||||
a.Insert(0, Val(i));
|
||||
if a.Last().(int) != Val(0) { t.Error("B") }
|
||||
if a.Len() != i { t.Errorf("A) wrong len %d (expected %d)", a.Len(), i) }
|
||||
a.Insert(0, val(i));
|
||||
if a.Last().(int) != val(0) { t.Error("B") }
|
||||
}
|
||||
for i := n-1; i >= 0; i-- {
|
||||
if a.Last().(int) != Val(0) { t.Error("C") }
|
||||
if a.Remove(0).(int) != Val(i) { t.Error("D") }
|
||||
if a.Len() != i { t.Errorf("E wrong len %d (expected %d)", a.Len(), i) }
|
||||
if a.Last().(int) != val(0) { t.Error("C") }
|
||||
if a.Delete(0).(int) != val(i) { t.Error("D") }
|
||||
if a.Len() != i { t.Errorf("E) wrong len %d (expected %d)", a.Len(), i) }
|
||||
}
|
||||
|
||||
if a.Len() != 0 { t.Errorf("F wrong len %d (expected 0)", a.Len()) }
|
||||
if a.Len() != 0 { t.Errorf("F) wrong len %d (expected 0)", a.Len()) }
|
||||
for i := 0; i < n; i++ {
|
||||
a.Push(Val(i));
|
||||
if a.Len() != i+1 { t.Errorf("G wrong len %d (expected %d)", a.Len(), i+1) }
|
||||
if a.Last().(int) != Val(i) { t.Error("H") }
|
||||
a.Push(val(i));
|
||||
if a.Len() != i+1 { t.Errorf("G) wrong len %d (expected %d)", a.Len(), i+1) }
|
||||
if a.Last().(int) != val(i) { t.Error("H") }
|
||||
}
|
||||
a.Init(0);
|
||||
if a.Len() != 0 { t.Errorf("I wrong len %d (expected 0)", a.Len()) }
|
||||
@ -70,17 +70,76 @@ func TestInsertRemoveClear(t *testing.T) {
|
||||
for j := 0; j < m; j++ {
|
||||
a.Push(j);
|
||||
for i := 0; i < n; i++ {
|
||||
x := Val(i);
|
||||
x := val(i);
|
||||
a.Push(x);
|
||||
if a.Pop().(int) != x { t.Error("J") }
|
||||
if a.Len() != j+1 { t.Errorf("K wrong len %d (expected %d)", a.Len(), j+1) }
|
||||
if a.Len() != j+1 { t.Errorf("K) wrong len %d (expected %d)", a.Len(), j+1) }
|
||||
}
|
||||
}
|
||||
if a.Len() != m { t.Errorf("L wrong len %d (expected %d)", a.Len(), m) }
|
||||
if a.Len() != m { t.Errorf("L) wrong len %d (expected %d)", a.Len(), m) }
|
||||
}
|
||||
|
||||
|
||||
func verify_slice(t *testing.T, x *array.Array, elt, i, j int) {
|
||||
for k := i; k < j; k++ {
|
||||
if x.At(k).(int) != elt {
|
||||
t.Errorf("M) wrong [%d] element %d (expected %d)", k, x.At(k).(int), elt)
|
||||
}
|
||||
}
|
||||
|
||||
s := x.Slice(i, j);
|
||||
for k, n := 0, j-i; k < n; k++ {
|
||||
if s.At(k).(int) != elt {
|
||||
t.Errorf("N) wrong [%d] element %d (expected %d)", k, x.At(k).(int), elt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func verify_pattern(t *testing.T, x *array.Array, a, b, c int) {
|
||||
n := a + b + c;
|
||||
if x.Len() != n {
|
||||
t.Errorf("O) wrong len %d (expected %d)", x.Len(), n)
|
||||
}
|
||||
verify_slice(t, x, 0, 0, a);
|
||||
verify_slice(t, x, 1, a, a + b);
|
||||
verify_slice(t, x, 0, a + b, n);
|
||||
}
|
||||
|
||||
|
||||
func make_array(elt, len int) *array.Array {
|
||||
x := array.New(len);
|
||||
for i := 0; i < len; i++ {
|
||||
x.Set(i, elt);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
func TestInsertArray(t *testing.T) {
|
||||
// 1
|
||||
a := make_array(0, 0);
|
||||
b := make_array(1, 10);
|
||||
a.InsertArray(0, b);
|
||||
verify_pattern(t, a, 0, 10, 0);
|
||||
// 2
|
||||
a = make_array(0, 10);
|
||||
b = make_array(1, 0);
|
||||
a.InsertArray(5, b);
|
||||
verify_pattern(t, a, 5, 0, 5);
|
||||
// 3
|
||||
a = make_array(0, 10);
|
||||
b = make_array(1, 3);
|
||||
a.InsertArray(3, b);
|
||||
verify_pattern(t, a, 3, 3, 7);
|
||||
// 4
|
||||
a = make_array(0, 10);
|
||||
b = make_array(1, 1000);
|
||||
a.InsertArray(8, b);
|
||||
verify_pattern(t, a, 8, 1000, 2);
|
||||
}
|
||||
|
||||
|
||||
/* currently doesn't compile due to linker bug
|
||||
func TestSorting(t *testing.T) {
|
||||
const n = 100;
|
||||
a := array.NewIntArray(n);
|
||||
@ -89,4 +148,3 @@ func TestSorting(t *testing.T) {
|
||||
}
|
||||
if sort.IsSorted(a) { t.Error("not sorted") }
|
||||
}
|
||||
*/
|
||||
|
@ -43,8 +43,8 @@ func (p *IntArray) Insert(i int, x int) {
|
||||
}
|
||||
|
||||
|
||||
func (p *IntArray) Remove(i int) int {
|
||||
return p.Array.Remove(i).(int)
|
||||
func (p *IntArray) Delete(i int) int {
|
||||
return p.Array.Delete(i).(int)
|
||||
}
|
||||
|
||||
|
||||
|
@ -50,7 +50,7 @@ func test1() {
|
||||
}
|
||||
|
||||
for v.Len() > 10 {
|
||||
v.Remove(10);
|
||||
v.Delete(10);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user