c语言接口与实现--第12章环的理解

不知不觉看到了第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个元素的环
这里写图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值