什么是关联式容器和序列时容器?二者的区别是什么?

关联式容器和序列容器都是C++ STL中的容器,它们主要的区别在于其存储内部元素的方式不同。

序列容器是按照元素插入的顺序来存储元素的,也就是说,元素在容器中的位置与其被插入的先后顺序是一致的。例如,vector、list 和deque都是序列容器。

而关联式容器不同,它们是通过比较关键字来对元素进行有序存储的。关键字可以是一个简单数据类型,例如整数或字符串,也可以是一个自定义的结构体或类,元素是按照关键字大小的顺序进行存储的。例如,set、map、multiset和multimap都是关联式容器。

因此,序列容器和关联式容器的最大区别在于内部元素的顺序。此外,在实现上,关联式容器一般采用平衡查找树或哈希表进行元素的存储和访问,而序列容器只需要链表或数组即可实现。两种容器的插入、删除和查找操作的时间复杂度也有所不同,因此需要根据实际问题的需求来选择使用何种容器。

C++ STL中主要有以下几种容器:

1. vector

vector是一个动态数组,可以随时改变大小,通过指针连续存储其元素。vector可以随机存取元素,但在插入或删除元素时效率较低,因为需要移动其后续元素。

2. list

list是一个双向链表,可以高效地插入和删除元素,但随机访问效率较低。

3. deque

deque也是一个双向队列,可以高效地插入和删除元素,并支持在两端进行随机存取,但效率不如vector。

4. set/multiset

set是关键字集合,其中的元素按照关键字自动排序,并且不允许重复。multiset在set的基础上,允许重复元素。

5. map/multimap

map是一个关键字-值集合,其中的元素按照关键字自动排序,并且不允许重复。multimap在map的基础上,允许重复键值对。

6. stack

stack是一个后进先出的容器,只支持在栈顶进行插入删除操作。

7. queue

queue是一个先进先出的容器,只支持在队列头尾进行插入删除操作。

以上这些容器都是通过模板类实现的。在实现中,STL使用了许多高效的算法和数据结构,例如基于红黑树的set/multiset和map/multimap,以及基于堆的优先队列等等。因此,使用STL提供的容器可以大大提高程序的效率和可维护性。

STL中的容器使用了不同的数据结构来实现不同的功能。

以下是几种常见的数据结构和对应的容器:

1. 动态数组(vector):使用普通数组实现,支持动态扩展大小和随机访问元素。

2. 双向链表(list):使用链表实现,在插入和删除元素时具有高效率,但是访问元素时效率较低。

3. 双端队列(deque):内部使用多个固定大小的数组实现,在两端进行操作时具有高效率。

4. 集合(set)、映射(map):基于红黑树实现,具有自动排序和二分查找的优势。set使用红黑树存储关键字,map使用红黑树存储键值对。

5. 散列表(unordered_set)、无序映射(unordered_map):基于散列表实现,通过将关键字或键哈希到不同的桶中,实现高效查找和插入。区别是unordered_map存储键值对,unordered_set存储关键字。

6. 栈(stack)和队列(queue):分别使用vector和deque来实现,提供了后进先出和先进先出的操作。

以上都是STL容器中常见的数据结构实现方式。在实现上,STL会利用C++的多态特性和迭代器等功能来实现通用的容器,使得容器的使用变得方便和简单。


//下面是非 STL 的 C++ 实现的散列表,使用了开放地址法解决冲突,哈希函数选取的是简单的取模法: 
 

#include <iostream>
#include <string>
 
class HashTable {
    private:
        static const int table_size = 100;
 
        struct Item {
            std::string key;
            std::string value;
        };
 
        Item* hash_table[table_size];
 
    public:
        HashTable();
        ~HashTable();
 
        int hash_func(std::string);
 
        void add_item(std::string, std::string);
        void remove_item(std::string);
        void find_item(std::string);
 
        void print_table();
};
 
HashTable::HashTable() {
//初始化散列表,把指针设为 NULL
    for(int i = 0; i < table_size; i++) {
        hash_table[i] = NULL;
    }
}
 
HashTable::~HashTable() {
    // 清除散列表中所有指针指向的内存
    for(int i = 0; i < table_size; i++) {
        if(hash_table[i] != NULL) {
            delete hash_table[i];
        }
    }
}
 
int HashTable::hash_func(std::string key) {
    // 简单的取模哈希函数
    int hash = 0;
    for(int i = 0; i < key.length(); i++) {
        hash = (hash + (int)key[i]) * 17;
    }
 
    return hash % table_size;
}
 
void HashTable::add_item(std::string key, std::string value) {
    int index = hash_func(key);
 
    //进行线性探测,知道找到一个空的位置为止
    while(hash_table[index] != NULL) {
        index++;
        index %= table_size;
    }
 
    hash_table[index] = new Item();
    hash_table[index]->key = key;
    hash_table[index]->value = value;
}
 
void HashTable::remove_item(std::string key) {
    int index = hash_func(key);
 
    while(hash_table[index] != NULL && hash_table[index]->key != key) {
        index++;
        index %= table_size;
    }
 
    if(hash_table[index] == NULL) {
        std::cout << "Key not found" << std::endl;
        return;
    } else {
        delete hash_table[index];
        hash_table[index] = NULL;
       
        std::cout << "Key removed" << std::endl;
    }
}
 
void HashTable::find_item(std::string key) {
    int index = hash_func(key);
 
    while(hash_table[index] != NULL && hash_table[index]->key != key) {
        index++;
        index %= table_size;
    }
 
    if(hash_table[index] == NULL) {
        std::cout << "Key not found" << std::endl;
        return;
    } else {
        std::cout << "Key: " << hash_table[index]->key << ", Value: " << hash_table[index]->value << std::endl;
    }
}
 
void HashTable::print_table() {
    for(int i = 0; i < table_size; i++)
     {
        if(hash_table[i] != NULL) {
            std::cout << "Index " << i << ": Key: " << hash_table[i]->key << ", Value: " << hash_table[i]->value << std::endl;
        }
    }
}
 
int main() 
{
    HashTable my_table;
 
    my_table.add_item("123", "abc");
    my_table.add_item("456", "def");
    my_table.add_item("789", "ghi");
 
    my_table.print_table();
 
    my_table.remove_item("123");
 
    my_table.print_table();
 
    my_table.find_item("789");
    my_table.find_item("123");
 
    return 0;
}

 /*
以上代码实现了添加、删除、查找和打印散列表的功能。
当添加元素时,先通过哈希函数计算键的索引,然后在散列表中进行线性探测,直到找到一个空的位置为止。
当删除元素时,同样也需要通过哈希函数找到键在散列表中的位置,然后删除该位置上的元素。
查找元素的方法与删除元素类似,但是需要在找到元素以后返回它的值。
*/

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值