【整理自用】一些数据结构题目、思路

Vector动态实现

思想:

  1. vector在定义时预留了一部分内存空间来用于存储新增的元素。
  2. 当添加元素时,如果vector空间大小不足,则会以原大小的两倍另外配置一块较大的新空间,然后将原空间内容拷贝过来,在新空间的内容末尾添加元素,并释放原空间。
  3. vector的空间动态增加大小,并不是在原空间之后的相邻地址增加新空间,因为vector的空间是线性连续分配的,不能保证原空间之后有可供配置的空间。因此,对vector的任何操作,一旦引起空间的重新配置,指向原vector的所有迭代器就会失效。

部分可借鉴的代码:
建立动态数组时使用模板类:

template<typename T>  
class Vector{  
public:  
//构造函数,复制构造函数以及析构函数  
Vector(int size=0):theSize(size),theCapacity(0+5)
{  
    objects=new T[theCapacity];  
}  
Vector(const Vector& rhs):objects(NULL)
{  
    operator=(rhs);  
}  
~Vector()
{  
    delete[] objects;  
}  

// 重载=号操作符  
const Vector& operator=(const Vector& rhs)
{  
    theCapacity=rhs.theCapacity;  
    theSize=rhs.theSize;  
    objects=new objects[this->theCapacity];  
    for(int i=0;i<this->theSize;i++)  
    objects[i]=rhs.objects[i];  
    return *this;  
}  

//内存空间不足时,以原大小的两倍另外配置一块较大的新空间。
//然后将原空间内容拷贝过来,在新空间的内容末尾添加元素,并释放原空间。
void resize(int newSize)
{  
    if(newSize>theCapacity)  
        reserve(newSize*2+1);  
    theSize=newSize;  
}  
//调整预留的空间,也就是实际上申请的内存的大小  
void reserve(int newCapacity)
{  
    if(newCapacity<theSize)  
        return;  
    T* oldObject=objects;  
    objects=new T[newCapacity];  
    theCapacity=newCapacity;  
    for(int i=0;i<theSize;i++)  
        objects[i]=oldObject[i];  
    delete objects;  
}  

//重载[]操作符  
T& operator[](int index)
{  
    return *(objects+index);  
}  
//成员常数函数
const T& operator[](int index)const
{  
    return *(objects+index);  
}   

//几个get函数,均为const成员,保证const对象也能调用  
bool isEmpty() const
{  
    return getSize()==0;  
}  
int capacity() const
{  
    return theCapacity;  
}  
int size() const
{  
    return theSize;  
}  

//push和pop操作  
void push_back(T t)
{  
    if(theSize==theCapacity)  
        reserve(theCapacity*2+1);  
    objects[theSize++]=t;  
}  
void pop_back()
{  
    theSize--;  
}  
T& back()
{  
    return objects[theSize-1];  
}  
const T& back()const
{  
    return objects[theSize-1];  
}  

// 迭代器  
typedef T* iterater;  
typedef const T* const_iterater;  

//begin end 等操作  
iterater begin()
{  
    return objects;  
}  
const_iterater begin() const
{  
    return objects;  
}  
iterater end()
{  
    return (objects+theSize);  
}  
const_iterater end() const
{  
    return (objects+theSize);  
}   
private:  
    T* objects;  
    int theSize;  
    int theCapacity;  
}

哈希表

在有网络的情况下,可以看以下几篇文章,相对浅显易懂讲述了关于哈希表的知识:
1. 浅谈算法和数据结构(11):哈希表
2. 为什么哈希表能够加快查找效率?
3. 哈希函数以及冲突解决常见方法
4. 举例子说明

下面是简单理解,具体还是需要看上述整理的工具书:
哈希表就是一种键-值(key-indexed)对应存储数据的结构(类似map,我们只要输入待查找的值即key,即可查找到其对应的值。

哈希的思路:
如果所有的键都是整数,那么就可以使用一个简单的无序数组来实现:将键作为索引,值即为其对应的值,这样就可以快速访问任意键的值。这是对于简单的键的情况,我们将其扩展到可以处理更加复杂的类型的键。

哈希查找步骤:
1. 使用哈希函数将被查找的键转换为数组的索引。理想的情况下,不同的键会被转换为不同的索引值,但是有些情况下我们需要处理多个键被哈希到同一个索引值的情况。
2. 处理哈希碰撞冲突。

哈希函数
哈希函数的构造方法很多,最好的情况是:关键字经过哈希函数得到一个随机的地址,以便使一组关键字的哈希地址均匀分布在整个地址空间中,从而减少冲突。通常若所给关键字不是自然数,将其转换为自然数。
冲突解决
当产生冲突时,进行二次计算。如:直接定址法建立一个数组,当哈希函数计算不同键对应于同一地址时,线性顺延查找到空位为止。
查找效率
由于查找关键字对应值的时候,是可以通过预先设计的哈希函数计算找到对应地址的,因此查找的效率可以达到O(1)。即使存在哈希碰撞,由于也是可以通过计算或者预先定义的线性表长度二次计算找到,相较于直接查找效率已经是大幅提高了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值