CS107 Assignment 3: vector and hashset

CS107 Assignment 3: vector and hashset

任务地址:https://see.stanford.edu/materials/icsppcs107/11-Assignment-3-Vector.pdf

任务1:The C vector

用c制作类似于c++的vector

一些区别:

1. c 没有 public 和 private 之分,所以不让用户见的函数在头文件cpp中用 static 修饰

2. c 没有方法,因此所有的函数的输入参数中都要加入 v,即没有 this->

3. c 用struct代替类的私有变量

一些注意事项:

1. 多用 assert( ) 确保用户的输入参数是正确的

2. memcpy( )不能用于有重叠部分的复制,此时用memmove( )替代

3. malloc( )和realloc( )里面参数要注意乘size

vector结构体:

typedef struct {
    void* elems;
    int elemSize;
    int initialAllocation;
    int logLength;
    int allocLength;
    VectorFreeFunction freeFn;
} vector;

vector.c:

#include "vector.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <search.h>

void VectorNew(vector *v, int elemSize, VectorFreeFunction freeFn, int initialAllocation)
{
    assert(elemSize > 0);
    v->elemSize = elemSize;

    assert(initialAllocation >0);
    v->allocLength = initialAllocation;
    v->initialAllocation = initialAllocation;

    v->logLength = 0;
    v->freeFn = freeFn;
    v->elems = malloc(v->allocLength *elemSize);
    assert(v->elems != NULL);
}

void VectorDispose(vector *v)
{
    if(v->freeFn != NULL)
    {
        for(int i=0; i< v->logLength; i++)
            v->freeFn(VectorNth(v,i));
    }
    free(v->elems);
}

int VectorLength(const vector *v)
{
    return v->logLength;
}

static void *VectorRawNth(const vector *v, int position)
{
    return (char *) v->elems + (position * v->elemSize);
}

void *VectorNth(const vector *v, int position)
{
    assert(position >= 0);
    assert(position < v->logLength);

    return (char*)v->elems + (v->elemSize * position);
}

void VectorReplace(vector *v, const void *elemAddr, int position)
{
    assert(position >= 0);
    assert(position < v->logLength);

    //先清理
    if (v->freeFn != NULL)
        v->freeFn(VectorNth(v, position));

    void* destAddr;
    destAddr = VectorNth(v,position);
    memcpy(destAddr, elemAddr, v->elemSize);
}

static void VectorElemShift(vector *v, int position, int delta)
{
    void *src = VectorRawNth(v, position);
    void *dest = VectorRawNth(v, position + delta);
    size_t len = (char *) VectorRawNth(v, v->logLength) - (char *) src;
    memmove(dest, src, len);
}

static void VectorGrow(vector *v)
{
    v->allocLength += v->initialAllocation;
    v->elems = realloc(v->elems, v->allocLength * v->elemSize);
    assert(v->elems != NULL);
}

void VectorInsert(vector *v, const void *elemAddr, int position)
{
    assert(position >= 0);
    assert(position <= v->logLength);

    if(v->logLength == v->allocLength)
        VectorGrow(v);

    VectorElemShift(v, position, 1);

    memcpy(VectorRawNth(v, position), elemAddr, v->elemSize);
    v->logLength++;
}

void VectorAppend(vector *v, const void *elemAddr)
{
    if(v->logLength == v->allocLength)
        VectorGrow(v);

    memcpy(VectorRawNth(v, v->logLength), elemAddr, v->elemSize);
    v->logLength++;
}

void VectorDelete(vector *v, int position)
{
    assert(position >= 0);
    assert(position < v->logLength);

    if (v->freeFn != NULL)
        v->freeFn(VectorNth(v, position));

    VectorElemShift(v, position+1, -1);
    v->logLength--;
}

void VectorSort(vector *v, VectorCompareFunction compare)
{
    assert(compare != NULL);
    qsort(v->elems, v->logLength, v->elemSize, compare);
}

void VectorMap(vector *v, VectorMapFunction mapFn, void *auxData)
{
    assert(mapFn != NULL);
    for (int i = 0; i < v->logLength; i++)
        mapFn(VectorNth(v, i), auxData);
}

static const int kNotFound = -1;
int VectorSearch(const vector *v, const void *key, VectorCompareFunction searchFn, int startIndex, bool isSorted)
{
    assert(key != NULL);
    assert(searchFn != NULL);
    assert(startIndex >= 0);
    assert(startIndex <= v->logLength);

    void *found;
    void *base = VectorRawNth(v, startIndex);
    size_t numElems = v->logLength - startIndex;

    if (isSorted)
        found = bsearch(key, base, numElems, v->elemSize, searchFn);
    else
        found = lfind(key, base, &numElems, v->elemSize, searchFn);  //num是指针接受传递

    if(found != NULL)
        return (int)( (char*)found - (char*)v )/v->elemSize;
    else
        return kNotFound;
}

结果展示:

 ------------------------- Starting the basic test...
First, here is the alphabet: ABCDEFGHIJKLMNOPQRSTUVWXYZ
After append digits: ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
After sorting: 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ
Found 'J' in sorted array? Yes. How about unsorted? Yes.
Found '$' in sorted array? No. How about unsorted? No.
After lowercase every other letter: 0123456789aBcDeFgHiJkLmNoPqRsTuVwXyZ
After insert dashes: 012-345-678-9aB-cDe-FgH-iJk-LmN-oPq-RsT-uVw-XyZ
After deleting dashes: 0123456789aBcDeFgHiJkLmNoPqRsTuVwXyZ
After adding and deleting to very end: 0123456789aBcDeFgHiJkLmNoPqRsTuVwXyZ
After changing all s to *: 0123456789aBcDeFgHiJkLmNoPqR*TuVwXyZ

------------------------- Starting the more advanced tests...
Generating all of the numbers between 0 and 3021376 (using some number theory). [All done]
Sorting all of those numbers. [Done]
Confirming everything was properly sorted. [Yep, it's sorted]
Erasing everything in the vector by repeatedly deleting the 100th-to-last remaining element (be patient).
	[Okay, almost done... deleting the last 100 elements... and we're all done... whew!]


------------------------- Starting the memory tests...
Creating a vector designed to store dynamically allocated C-strings.
Populating the char * vector with the question words.
Mapping over the char * vector (ask yourself: why are char **'s passed to PrintString?!!)
	why
	how
	where
	what
	who
Finally, destroying the char * vector.

任务2: The C hashset

用刚刚制作的vector制作hashset

所谓hashset,就是把数存到hash桶里,所以事先设定桶的个数,还有hash函数(判断把数放哪个桶里)

使用hashset,可以减少查找的时间,先判断在哪个桶里,再直接在桶里找

hashset结构体:

typedef struct
{
    int elemSize;
    int numBuckets;
    vector* buckets;
    HashSetHashFunction hashfn;
    HashSetCompareFunction comparefn;
    HashSetFreeFunction freefn;
} hashset;

hashset.cpp:

#include "hashset.h"
#include <assert.h>
#include <stdlib.h>
#include <string.h>

void HashSetNew(hashset *h, int elemSize, int numBuckets,
                HashSetHashFunction hashfn, HashSetCompareFunction comparefn, HashSetFreeFunction freefn)
{
    assert(elemSize > 0);
    assert(numBuckets > 0);
    assert(hashfn != NULL);
    assert(comparefn != NULL);

    h->elemSize = elemSize;
    h->numBuckets = numBuckets;
    h->hashfn = hashfn;
    h->comparefn = comparefn;
    h->freefn = freefn;

    h->buckets = (vector*)malloc(sizeof(vector) * numBuckets);

    for (int i = 0; i < numBuckets; i++) {
        VectorNew(h->buckets + i, elemSize, freefn, 10);
    }
}

void HashSetDispose(hashset *h)
{
    if (h->freefn != NULL)
    {
        for (int i = 0; i < h->numBuckets; i++)
            VectorDispose(h->buckets + i);
    }
    free(h->buckets);

}

int HashSetCount(const hashset *h)
{
    int count = 0;
    for (int i = 0; i < h->numBuckets; i++)
        count += VectorLength(h->buckets + i);
    return count;
}

void HashSetMap(hashset *h, HashSetMapFunction mapfn, void *auxData)
{
    assert(mapfn != NULL);
    for (int i = 0; i < h->numBuckets; i++)
        VectorMap(h->buckets + i, mapfn, auxData);
}

void HashSetEnter(hashset *h, const void *elemAddr)
{
    void *existing = HashSetLookup(h, elemAddr);
    if (existing == NULL)
    {
        int bucket = h->hashfn(elemAddr, h->numBuckets);
        assert(bucket >= 0);
        assert(bucket < h->numBuckets);

        vector *v = h->buckets + bucket;
        VectorAppend(v, elemAddr);
        VectorSort(v, h->comparefn);
    }
    //想不到把,就算找到了也要加进去
    else
        memcpy(existing, elemAddr, h->elemSize);
}

void *HashSetLookup(const hashset *h, const void *elemAddr)
{
    assert(elemAddr != NULL);

    //找到桶号
    int bucket = h->hashfn(elemAddr, h->numBuckets);
    assert(bucket >= 0);
    assert(bucket < h->numBuckets);

    vector *v = h->buckets + bucket;
    int pos = VectorSearch(v, elemAddr, h->comparefn, 0, true);
    return pos == -1 ? NULL : VectorNth(v, pos);
}

结果展示:

------------------------- Starting the HashTable test
Here is the unordered contents of the table:
Character h occurred  164 times
Character i occurred  185 times
Character k occurred   15 times
Character l occurred  122 times
Character m occurred   67 times
Character n occurred  263 times
Character o occurred  240 times
Character p occurred   82 times
Character q occurred   64 times
Character r occurred  319 times
Character s occurred  289 times
Character t occurred  406 times
Character u occurred  206 times
Character v occurred   35 times
Character w occurred   15 times
Character x occurred    1 times
Character y occurred   68 times
Character z occurred    3 times
Character a occurred  214 times
Character b occurred   44 times
Character c occurred  279 times
Character d occurred  111 times
Character e occurred  500 times
Character f occurred  146 times
Character g occurred   13 times

Here are the trials sorted by char: 
Character a occurred  214 times
Character b occurred   44 times
Character c occurred  279 times
Character d occurred  111 times
Character e occurred  500 times
Character f occurred  146 times
Character g occurred   13 times
Character h occurred  164 times
Character i occurred  185 times
Character k occurred   15 times
Character l occurred  122 times
Character m occurred   67 times
Character n occurred  263 times
Character o occurred  240 times
Character p occurred   82 times
Character q occurred   64 times
Character r occurred  319 times
Character s occurred  289 times
Character t occurred  406 times
Character u occurred  206 times
Character v occurred   35 times
Character w occurred   15 times
Character x occurred    1 times
Character y occurred   68 times
Character z occurred    3 times

Here are the trials sorted by occurrence & char: 
Character e occurred  500 times
Character t occurred  406 times
Character r occurred  319 times
Character s occurred  289 times
Character c occurred  279 times
Character n occurred  263 times
Character o occurred  240 times
Character a occurred  214 times
Character u occurred  206 times
Character i occurred  185 times
Character h occurred  164 times
Character f occurred  146 times
Character l occurred  122 times
Character d occurred  111 times
Character p occurred   82 times
Character y occurred   68 times
Character m occurred   67 times
Character q occurred   64 times
Character b occurred   44 times
Character v occurred   35 times
Character k occurred   15 times
Character w occurred   15 times
Character g occurred   13 times
Character z occurred    3 times
Character x occurred    1 times

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值