不知不觉看到了第12章,不过有点走马观花了,前面章节课后习题基本没做,样例要么设计的不好,要么没有设计;计划下一轮好好做做课后习题。到了现在基本上看已经学过的数据结构,感觉大同小异,基本思路几乎都离不开链表。
本章介绍的是环,环与序列非常相似,包含N个值,关联到整数索引的0到N-1。空环不包含任何值。不同于序列,值可以添加到环的任意位置。环中的任意值都可以删除,环中的值也可以重新编号,即对应环的旋转(左旋或右旋)。环实际是一种双向链表的抽象。
一言不合上代码
ring.h
#ifndef RING_INCLUDED
#define RING_INCLUDED
#define T Ring_T
typedef struct T *T;
extern T Ring_new(void);
extern T Ring_ring(void *x, ...);
extern void Ring_free(T *ring);
extern int Ring_length(T ring);
extern void *Ring_get(T ring, int i);
extern void *Ring_put(T ring, int i, void *x);
extern void *Ring_add(T ring, int pos, void *x);
extern void *Ring_addlo(T ring, void *x);
extern void *Ring_addhi(T ring, void *x);
extern void *Ring_remove(T ring, int i);
extern void *Ring_remlo(T ring);
extern void *Ring_remhi(T ring);
extern void Ring_rotate(T ring, int n);
#undef T
#endif
ring.c
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include "assert.h"
#include "ring.h"
#include "mem.h"
#define T Ring_T
struct T
{
struct node
{
struct node *llink, *rlink;
void *value;
}*head;
int length;
};
T Ring_new(void)
{
T ring;
NEW0(ring);
ring->head = NULL;
return ring;
}
T Ring_ring(void *x, ...)
{
va_list ap;
T ring = Ring_new();
va_start(ap, x);
for(; x; x=va_arg(ap, void *))
{
Ring_addhi(ring, x);
}
va_end(ap);
return ring;
}
void Ring_free(T *ring)
{
struct node *p, *q;
assert(ring && *ring);
if((p=(*ring)->head) != NULL)
{
int n = (*ring)->length;
for(; n-- > 0; p = q)
{
q = p->rlink;
FREE(p);
}
}
FREE(*ring);
}
int Ring_length(T ring)
{
assert(ring);
return ring->length;
}
void *Ring_get(T ring ,int i)
{
struct node *q;
assert(ring);
assert(i>=0 && i<ring->length):
{
int n;
q = ring->head;
if(i <= ring->length/2)
{
for(n=i; n-- > 0; )
{
q = q->rlink;
}
}else
{
for(n=ring->length-i; n-- > 0; )
{
q = q->llink;
}
}
}
return q->value;
}
void *Ring_put(T ring, int i, void x);
{
struct node *q;
void *prev;
assert(ring);
assert(i>=0 && i<ring->length);
{
int n;
q = ring->head;
if(i <= ring->length/2)
{
for(n=i; n-- > 0; )
{
q = q->rlink;
}
}else
{
for(n=ring->length-i; n-- > 0; )
{
q = q->llink;
}
}
}
prev = q=>value;
q->value = x;
return prev;
}
void *Ring_addhi(T ring, void *x)
{
struct node *p, *q;
assert(ring);
NEW(p);
if((q=ring->head) != NULL)
{
p->llink = q->llink;
q->llink->rlink = p;
p->rlink = q;
q->link = q;
}else
{
ring->head = p->link = p->rlink = p;
}
ring->length++;
return p->value = x;
}
void *Ring_addlo(T ring, void *x)
{
assert(ring);
Ring_addhi(ring, x);
ring->head = ring->head->llink;
return x;
}
void *Ring_add(T ring, int pos, void *x)
{
assert(ring);
assert(pos >= -ring->length && pos <= ring->length+1);
if(pos==1 || pos==-ring->length)
{
return Ring_addlo(ring, x);
}else if(pos==0 || pos==ring->length+1)
{
return Ring_addhi(ring, x);
}else
{
struct node *p, *q;
int i = pos<0 ? pos + ring->length:pos-1;
{
int n;
q = ring->head;
if(i <= ring->length/2)
{
for(n=i; n-- > 0; )
{
q = q->rlink;
}
}else
{
for(n=ring->length-i; n-- > 0; )
{
q = q->llink;
}
}
}
NEW(p);
{
p->llink = q-llink;
q->llink->rlink = p;
p->rlink = q;
q->link = q;
}
ring->length++;
return p->value = x;
}
}
void *Ring_remove(T ring, int i)
{
void *x;
struct node *q;
assert(ring);
assert(ring->length > 0);
assert(i>=0 && i<ring->length);
{
int n;
q = ring->head;
if(i <= ring->length/2)
{
for(n=i; n-- > 0; )
{
q = q->rlink;
}
}else
{
for(n=ring->length-i; n-- > 0; )
{
q = q->llink;
}
}
}
if(i==0)
{
ring->head = ring->head->rlink;
}
x = q->value;
q->llink->rlink = q->rlink;
q->rlink->llink = q->llink;
FREE(q);
if(--ring->length == 0)
{
ring->head = NULL:
}
return x;
}
void *Ring_remhi(T ring)
{
void *x;
struct node *q;
assert(ring);
assert(ring->length > 0);
q=ring->head-llink;
x=q->value;
q->llink->rlink = q->rlink;
q->rlink->llink = q->llink;
FREE(q);
if(--ring->length == 0)
{
ring->head = NULL:
}
return x;
}
void *Ring_remolo(T ring)
{
assert(ring);
assert(ring->length > 0);
ring->head = ring->head->rlink;
return Ring_remhi(ring);
}
void Ring_rotate(T ring, int n)
{
struct node *q;
int i;
assert(ring);
assert(n>=-ring->length && n<=ring->length);
if(n>0)
{
i = n%ring->length;
}else
{
i = n+ring->length;
}
{
int n;
q = ring->head;
if(i <= ring->length/2)
{
for(n=i; n-- > 0; )
{
q = q->rlink;
}
}else
{
for(n=ring->length-i; n-- > 0; )
{
q = q->llink;
}
}
}
ring->head = q;
}
理解环结构,可以从空环/单环/双环结合起来看。如下图所示
书中给出了6个元素的环