📜  在没有 C++ STL 容器的情况下实现集合

📅  最后修改于: 2022-05-13 01:55:29.032000             🧑  作者: Mango

在没有 C++ STL 容器的情况下实现集合

Set 是不同元素的集合。元素一旦添加就无法修改。有各种与集合相关的运算,例如并集、交集、幂集、笛卡尔积、集差、补集和相等。

设置方法:

  • add(data) – 将“数据”添加到集合中
  • unionSet(s) – 返回 set 与 set 's' 的并集
  • 交叉集(s)–返回与集合's'的交集
  • 补集(U)——返回集合的补集与通用集“U”
  • 运算符-(s) – 返回 set 和 set 's' 的差异
  • 运算符==(s) – 返回集合是否等于集合 's'
  • displayProduct(s) – 打印 set 和 set 's' 的笛卡尔积到控制台
  • displayPowerSet() – 将电源集打印到控制台
  • toArray() – 将集合作为其元素的数组返回
  • contains(s) – 返回集合是否包含元素 's'
  • displaySet() – 将集合打印到控制台
  • getSize() – 返回集合的大小

下面是一个使用二叉搜索树的集合的实现:

C++
// C++ implementation of the approach
#include 
#include 
#include 
#include 
#include 
using namespace std;
 
// Structure to implement a node of a BST
template 
struct Node {
 
    // The data content of the node
    T data;
 
    // Link to the left child
    Node* left;
 
    // Link to the right child
    Node* right;
 
public:
    // Function to print the inorder
    // traversal of the BST
    void inorder(Node* r)
    {
        if (r == NULL) {
            return;
        }
        inorder(r->left);
        cout << r->data << " ";
        inorder(r->right);
    }
 
    /*
        Function to check if BST contains a node
        with the given data
         
        @param r pointer to the root node
        @param d the data to search
        @return 1 if the node is present else 0
    */
    int containsNode(Node* r, T d)
    {
        if (r == NULL) {
            return 0;
        }
        int x = r->data == d ? 1 : 0;
        return x | containsNode(r->left, d) | containsNode(r->right, d);
    }
 
    /*
        Function to insert a node with
        given data into the BST
         
        @param r pointer to the root node
        @param d the data to insert
        @return pointer to the root of the resultant BST
    */
    Node* insert(Node* r, T d)
    {
 
        // Add the node when NULL node is encountered
        if (r == NULL) {
            Node* tmp = new Node;
            tmp->data = d;
            tmp->left = tmp->right = NULL;
            return tmp;
        }
 
        // Traverse the left subtree if data
        // is less than the current node
        if (d < r->data) {
            r->left = insert(r->left, d);
            return r;
        }
 
        // Traverse the right subtree if data
        // is greater than the current node
        else if (d > r->data) {
            r->right = insert(r->right, d);
            return r;
        }
        else
            return r;
    }
};
 
// Class to implement a Set using BST
template 
class Set {
 
    // Pointer to the root of the
    // BST storing the set data
    Node* root;
 
    // The number of elements in the set
    int size;
 
public:
    // Default constructor
    Set()
    {
        root = NULL;
        size = 0;
    }
 
    // Copy constructor
    Set(const Set& s)
    {
        root = s.root;
        size = s.size;
    }
 
    /*
        Function to Add an element to the set
 
        @param data the element to add to the set
    */
    void add(const T data)
    {
        if (!root->containsNode(root, data)) {
            root = root->insert(root, data);
            size++;
        }
    }
 
    /*
        Function to compute the union of two sets
         
        @param s set to find union with
        @return the union set
    */
    Set unionSet(Set& s)
    {
        Set res;
 
        // Second set is returned
        // if first set is empty
        if (root == NULL)
            return res;
 
        // First set is returned
        // if second set is empty
        if (s.root == NULL)
            return *this;
 
        // The elements of the first set
        // are added to the resultant set
        stack*> nodeStack;
        nodeStack.push(root);
 
        // Preorder traversal of the BST
        while (!nodeStack.empty()) {
            Node* node;
            node = nodeStack.top();
            nodeStack.pop();
 
            // The data is added to the resultant set
            res.add(node->data);
 
            if (node->right)
                nodeStack.push(node->right);
            if (node->left)
                nodeStack.push(node->left);
        }
 
        // The elements of the second set
        // are added to the resultant set
        stack*> nodeStack1;
        nodeStack1.push(s.root);
 
        while (!nodeStack1.empty()) {
            Node* node;
            node = nodeStack1.top();
            nodeStack1.pop();
 
            res.add(node->data);
 
            if (node->right)
                nodeStack1.push(node->right);
            if (node->left)
                nodeStack1.push(node->left);
        }
 
        return res;
    }
 
    /**
        Computes the intersection of two sets
         
        @param s the set to find intersection with
        @return the intersection set
    */
    Set intersectionSet(Set& s)
    {
        Set res;
        stack*> nodeStack;
        nodeStack.push(root);
 
        while (!nodeStack.empty()) {
            Node* node;
            node = nodeStack.top();
            nodeStack.pop();
            if (s.contains(node->data)) {
                res.add(node->data);
            }
            if (node->right)
                nodeStack.push(node->right);
            if (node->left)
                nodeStack.push(node->left);
        }
        return res;
    }
 
    /*
        Function to compute the complement of the set
         
        @param U the universal set
        @return the complement set
    */
    Set complementSet(Set& U)
    {
        return (U - *this);
    }
 
    /*
        Function to compute the difference of two sets
         
        @param s the set to be subtracted
        @return the difference set
    */
    Set operator-(Set& s)
    {
        Set res;
        stack*> nodeStack;
        nodeStack.push(this->root);
 
        while (!nodeStack.empty()) {
            Node* node;
            node = nodeStack.top();
            nodeStack.pop();
            if (!s.contains(node->data)) {
                res.add(node->data);
            }
            if (node->right)
                nodeStack.push(node->right);
            if (node->left)
                nodeStack.push(node->left);
        }
        return res;
    }
 
    /*
        Function that checks equality of two sets
         
        @param s set to check equality with
        @return boolean value denoting result of check
    */
    bool operator==(Set& s)
    {
        if (s.getSize() != size) {
            return false;
        }
        stack*> nodeStack;
        nodeStack.push(this->root);
 
        while (!nodeStack.empty()) {
            Node* node;
            node = nodeStack.top();
            nodeStack.pop();
            if (!s.contains(node->data)) {
                return false;
            }
            if (node->right)
                nodeStack.push(node->right);
            if (node->left)
                nodeStack.push(node->left);
        }
        return true;
    }
 
    /*
        Function to print the cartesian product of two sets
         
        @param s the set to find product with
    */
    void displayProduct(Set& s)
    {
        int i, j, n2 = s.getSize();
        T* A = toArray();
        T* B = s.toArray();
 
        i = 0;
 
        cout << "{ ";
        for (i = 0; i < size; i++) {
            for (j = 0; j < n2; j++) {
                cout << "{ " << A[i] << " " << B[j] << " } ";
            }
        }
        cout << "}" << endl;
    }
 
    // Function to print power set of the set
    void displayPowerSet()
    {
        int n = pow(2, size);
        T* A = toArray();
        int i;
        while (n-- > 0) {
            cout << "{ ";
            for (int i = 0; i < size; i++) {
                if ((n & (1 << i)) == 0) {
                    cout << A[i] << " ";
                }
            }
            cout << "}" << endl;
        }
    }
 
    /*
        Function to convert the set into an array
         
        @return array of set elements
    */
    T* toArray()
    {
        T* A = new T[size];
        int i = 0;
        stack*> nodeStack;
        nodeStack.push(this->root);
 
        while (!nodeStack.empty()) {
            Node* node;
            node = nodeStack.top();
            nodeStack.pop();
 
            A[i++] = node->data;
 
            if (node->right)
                nodeStack.push(node->right);
            if (node->left)
                nodeStack.push(node->left);
        }
        return A;
    }
 
    /*
        Function to check whether the set contains an element
         
        @param data the element to search
        @return relut of check
    */
    bool contains(T data)
    {
        return root->containsNode(root, data) ? true : false;
    }
 
    // Function to print the contents of the set
    void displaySet()
    {
        cout << "{ ";
        root->inorder(root);
        cout << "}" << endl;
    }
 
    /*
        Function to return the current size of the Set
         
        @return size of set
    */
    int getSize()
    {
        return size;
    }
};
 
// Driver code
int main()
{
 
    // Create Set A
    Set A;
 
    // Add elements to Set A
    A.add(1);
    A.add(2);
    A.add(3);
    A.add(2);
 
    // Display the contents of Set A
    cout << "A = ";
    A.displaySet();
    cout << "P(A) = " << endl;
    A.displayPowerSet();
 
    // Check if Set A contains some elements
    cout << "A " << (A.contains(3) ? "contains"
                                   : "does not contain")
         << " 3" << endl;
    cout << "A " << (A.contains(4) ? "contains"
                                   : "does not contain")
         << " 4" << endl;
    cout << endl;
 
    // Create Set B
    Set B;
 
    // Insert elements to Set B
    B.add(1);
    B.add(2);
    B.add(4);
 
    // Display the contents of Set B
    cout << "B = ";
    B.displaySet();
    cout << "P(B) = " << endl;
    B.displayPowerSet();
    cout << endl;
 
    // Create Set C
    Set C;
    C.add(1);
    C.add(2);
    C.add(4);
 
    // Display the contents of Set C
    cout << "C = ";
    C.displaySet();
    cout << endl;
 
    // Set F contains the difference
    // of the Sets A and B
    Set F = A - B;
    cout << "A - B = ";
    F.displaySet();
    cout << endl;
 
    // Set D contains the union
    // of the Sets A and B
    Set D = A.unionSet(B);
    cout << "A union B = ";
    D.displaySet();
    cout << endl;
 
    // Set E contains the intersection
    // of the Sets A and B
    Set E = A.intersectionSet(B);
    cout << "A intersection B = ";
    E.displaySet();
    cout << endl;
 
    // Display the product
    cout << "A x B = ";
    A.displayProduct(B);
    cout << endl;
 
    // Equality tests
    cout << "Equality of Sets:" << endl;
 
    cout << "A "
         << ((A == B) ? "" : "!") << "= B"
         << endl;
    cout << "B "
         << ((B == C) ? "" : "!") << "= C"
         << endl;
    cout << "A "
         << ((A == C) ? "" : "!") << "= C"
         << endl;
    cout << endl;
 
    Set U;
    U.add(1);
    U.add(2);
    U.add(3);
    U.add(4);
    U.add(5);
    U.add(6);
    U.add(7);
 
    // Complements of the respective Sets
    Set A1 = A.complementSet(U);
    Set B1 = B.complementSet(U);
    Set C1 = C.complementSet(U);
 
    cout << "A' = ";
    A1.displaySet();
    cout << "B' = ";
    B1.displaySet();
    cout << "C' = ";
    C1.displaySet();
 
    return 0;
}


输出:
A = { 1 2 3 }
P(A) = 
{ }
{ 1 }
{ 2 }
{ 1 2 }
{ 3 }
{ 1 3 }
{ 2 3 }
{ 1 2 3 }
A contains 3
A does not contain 4

B = { 1 2 4 }
P(B) = 
{ }
{ 1 }
{ 2 }
{ 1 2 }
{ 4 }
{ 1 4 }
{ 2 4 }
{ 1 2 4 }

C = { 1 2 4 }

A - B = { 3 }

A union B = { 1 2 3 4 }

A intersection B = { 1 2 }

A x B = { { 1 1 } { 1 2 } { 1 4 } { 2 1 } { 2 2 } { 2 4 } { 3 1 } { 3 2 } { 3 4 } }

Equality of Sets:
A != B
B = C
A != C

A' = { 4 5 6 7 }
B' = { 3 5 6 7 }
C' = { 3 5 6 7 }

可以使用 AVL 树或红黑树代替简单的 BST 使插入和搜索的最坏情况复杂度为 O(log(n))。
关于使用 STL set,请参考这篇文章 Set in C++ Standard Template Library (STL)。

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程