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個元素的環
這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章