19 - Custom Templatized Data Structure

目录:

  1. List
  2. Stack -> 其他:普通的类继承 & 模板类继承
  3. Queue
  4. Tree & TreeNode & TestTree  -> 简单的递归


1. List 定义

//
// Created by  on 2021/7/23.
//

#ifndef PRACTICE15_LIST_H
#define PRACTICE15_LIST_H

#include <iostream>
#include "ListNode.h"
using namespace std;

template<typename NODETYPE>
class List{
public:
    bool isEmpty() const {
        return firstPtr == nullptr;
    }
    
    void print() const {
        if (isEmpty()) {
            cout << "The list is empty\n\n";
            return;
        }
        ListNode<NODETYPE>* currentPtr{firstPtr};
        cout << "The list is: ";
        while (currentPtr != nullptr){
            cout << currentPtr->data << " ";
            currentPtr = currentPtr->nextPtr;
        }
        cout << "\n\n";
    }
    ~List(){
        if(!isEmpty()) {
            cout << "Destory is not empty";
            ListNode<NODETYPE>* currentPtr{firstPtr};
            ListNode<NODETYPE>* tempPtr{nullptr};

            while (currentPtr != nullptr){
                tempPtr = currentPtr;
                cout << tempPtr->data << "\n";
                currentPtr = currentPtr -> nextPtr;
                delete tempPtr;
            }
        }
        cout << "All nodes destroyed\n\n";
    }

    // insert front
    void insertAtFront(ListNode<NODETYPE>& value) {
        ListNode<NODETYPE>* newPtr{getNewNode(value)};
        if (isEmpty()) {
            firstPtr = lastPtr = newPtr;
        }
        else {
            newPtr->nextPtr = firstPtr;
            firstPtr = newPtr;
        }
    }

    // insert back
    void insertAtBack(ListNode<NODETYPE>& value) {
        ListNode<NODETYPE>* newPtr{getNewNode(value)};
        if (isEmpty()){
            firstPtr = lastPtr = newPtr;
        }
        else {
            lastPtr->nextPtr = newPtr;
            lastPtr = newPtr;
        }
    }

    // delete front
    bool removeFromFront(NODETYPE& value) {
        if (isEmpty()){
            return false;
        }
        else {
            ListNode<NODETYPE>* tempPtr{firstPtr};
            if (firstPtr == lastPtr) {
                firstPtr = lastPtr = nullptr;
            }
            else {
                firstPtr = firstPtr->nextPtr;
            }
            value = tempPtr->data;
            delete tempPtr;
            return true;
        }
    }

    // delete back
    bool removeFromBack(NODETYPE& value) {
        if (isEmpty()){
            return false;
        }
        else {
            ListNode<NODETYPE>* tempPtr{lastPtr};
            if(firstPtr == lastPtr) {
                firstPtr = lastPtr = nullptr;
            }
            else {
                ListNode<NODETYPE>* currentPtr{firstPtr};
                while (currentPtr->nextPtr != lastPtr){
                    currentPtr = currentPtr -> nextPtr;
                }
                lastPtr = currentPtr;
                currentPtr->nextPtr = nullptr;
            }
            value = tempPtr->data;
            delete tempPtr;
            return true;
        }

    }


private:
    ListNode<NODETYPE>* firstPtr{nullptr};
    ListNode<NODETYPE>* lastPtr{nullptr};
    
    ListNode<NODETYPE>* getNewNode(const NODETYPE& value) {
        return new ListNode<NODETYPE>{value};
    }
};



#endif //PRACTICE15_LIST_H

ListNode 定义

//
// Created by  on 2021/7/23.
//

#ifndef PRACTICE15_LISTNODE_H
#define PRACTICE15_LISTNODE_H

template<typename NODETYPE> class List; // 类模板

template<typename NODETYPE>
class ListNode{
    friend class List<NODETYPE>;
public:
    // constuctor
    explicit ListNode(const NODETYPE& info):data{info}, nextPtr{nullptr} {}

    // return data in node
    NODETYPE getData() const {return data;}

private:
    // data
    NODETYPE data;
    ListNode<NODETYPE>* nextPtr;
};


#endif //PRACTICE15_LISTNODE_H

原理:

 

注意编译的 CMakeLists.txt 的用法哈~~


 2、普通的类继承 & 模板类继承

普通的类继承,注意复习虚函数:https://zhuanlan.zhihu.com/p/259875110 


#include <iostream>
using namespace std;

class A
{
public:
    A() {};
    ~A() {};
    virtual void func(){
        cout << "this is A" << endl;
    }
};

class B : public A
{
public:
    virtual void func() {
        cout << "this is B" << endl;
    }
};

int main(){
    A* c = new B();
    c ->func();  //this is B
    c ->A::func(); //this is A

    B b;
    b.func();  //this is B

    A a;
    a.func();  //this is A

    b.A::func();  //this is A

}

/*
 *
this is B
this is A
this is B
this is A
this is A

 */

模板类的继承:Stack.h  定义

// Stack class-template definition.
#ifndef STACK_H
#define STACK_H

#include "List.h" // List class definition

template<typename STACKTYPE>
class Stack : private List<STACKTYPE> {
public:
   // push calls the List function insertAtFront
   void push(const STACKTYPE& data) {
       this->insertAtFront(data);  // 这里修改成了this
   }

   // pop calls the List function removeFromFront
   bool pop(STACKTYPE& data) {
      return this->removeFromFront(data);
   }

   // isStackEmpty calls the List function isEmpty
   bool isStackEmpty() const {
      return this->isEmpty();
   }

   // printStack calls the List function print
   void printStack() const {
      this->print();
   }
};

#endif

测试stack 小程序


#include <iostream>
#include "Stack.h" // Stack class definition
using namespace std;

int main() {
   Stack<int> intStack; // create Stack of ints

   cout << "processing an integer Stack" << endl;

   // push integers onto intStack
   for (int i{0}; i < 3; ++i) {
      intStack.push(i);
      intStack.printStack();
   }

   int popInteger; // store int popped from stack

   // pop integers from intStack
   while (!intStack.isStackEmpty()) {
      intStack.pop(popInteger);
      cout << popInteger << " popped from stack" << endl;
      intStack.printStack();
   }

   Stack<double> doubleStack; // create Stack of doubles
   double value{1.1};

   cout << "processing a double Stack" << endl;

   // push floating-point values onto doubleStack
   for (int j{0}; j < 3; ++j) {
      doubleStack.push(value);
      doubleStack.printStack();
      value += 1.1;
   }

   double popDouble; // store double popped from stack

   // pop floating-point values from doubleStack
   while (!doubleStack.isStackEmpty()) {
      doubleStack.pop(popDouble);
      cout << popDouble << " popped from stack" << endl;
      doubleStack.printStack();
   }
}

/*

processing an integer Stack
The list is: 0 

The list is: 1 0 

The list is: 2 1 0 

2 popped from stack
The list is: 1 0 

1 popped from stack
The list is: 0 

0 popped from stack
The list is empty

processing a double Stack
The list is: 1.1 

The list is: 2.2 1.1 

The list is: 3.3 2.2 1.1 

3.3 popped from stack
The list is: 2.2 1.1 

2.2 popped from stack
The list is: 1.1 

1.1 popped from stack
The list is empty

All nodes destroyed

All nodes destroyed
*/

3. Queue

//
// Created by  on 2021/7/26.
//

#include "Queue.h"
#include <iostream>
using namespace std;

int main(){
    Queue<int> intQueue;
    for(int i{0}; i<3 ; ++i){
        intQueue.enqueue(i);
        intQueue.printQueue();
    }

    int dequeueInteger;
    while(!intQueue.isQueueEmpty()){
        intQueue.dequeue(dequeueInteger);
        cout << dequeueInteger << " dequeued" << endl;
        intQueue.printQueue();
    }

    cout << "************************;" << endl;

    Queue<double> doubleQueue;
    double value{1.1};
    for (double j{0}; j<3; ++j){
        doubleQueue.enqueue(value);
        doubleQueue.printQueue();
        value += j;
    }

    double dequeueDouble;
    while(!doubleQueue.isQueueEmpty()){
        doubleQueue.dequeue(dequeueDouble);
        cout << dequeueDouble << " dequeued" << endl;
        doubleQueue.printQueue();
    }
}


/*
(base) ➜  build ./bin/list_demo 
The list is: 0 

The list is: 0 1 

The list is: 0 1 2 

0 dequeued
The list is: 1 2 

1 dequeued
The list is: 2 

2 dequeued
The list is empty

************************;
The list is: 1.1 

The list is: 1.1 1.1 

The list is: 1.1 1.1 2.1 

1.1 dequeued
The list is: 1.1 2.1 

1.1 dequeued
The list is: 2.1 

2.1 dequeued
The list is empty

All nodes destroyed

All nodes destroyed


*/


4. Tree & TreeNode & TestTree  -> 简单的递归

TreeNode.h

#ifndef BASE_CPP_TREENODE_H
#define BASE_CPP_TREENODE_H

template<typename NODETYPE>
class Tree;

template<typename NODETYPE>
class TreeNode {
    friend class Tree<NODETYPE>;
public:
    TreeNode(const NODETYPE &d) : data{d} {}
    NODETYPE getData() const { return data; }

private:
    NODETYPE data;
    TreeNode<NODETYPE> *rightPtr{nullptr};
    TreeNode<NODETYPE> *leftPtr{nullptr};
};


#endif //BASE_CPP_TREENODE_H

Tree.h


#ifndef BASE_CPP_TREE_H
#define BASE_CPP_TREE_H

#include <iostream>
#include "TreeNode.h"
using namespace  std;

template<typename NODETYPE>
class Tree {
public:
    // insert node in Tree
    void insertNode(const NODETYPE &value) {
        insertNodeHelper(&rootPtr, value);
    }

    // begin preorder traversal of Tree
    void preOrderTraversal() const {
        preOrderHelper(rootPtr);
    }

    // begin inorder traversal of Tree
    void inOrderTraversal() const {
        inOrderHelper(rootPtr);
    }

    // begin postorder traversal of Tree
    void postOrderTraversal() const {
        postOrderHelper(rootPtr);
    }


private:
    TreeNode<NODETYPE> *rootPtr{nullptr};

    // 这里有点二叉搜索树的策略,左根值<中间<右根值
    void insertNodeHelper(TreeNode<NODETYPE> **ptr, const NODETYPE &value) {
        if (*ptr == nullptr) { // subtree is empty
            *ptr = new TreeNode<NODETYPE>(value);
        } else { // subtree is not empty
            if (value < (*ptr)->data) {
                insertNodeHelper(&((*ptr)->leftPtr), value);
            } else {
                if (value > (*ptr)->data) {
                    insertNodeHelper(&((*ptr)->rightPtr), value);
                } else {
                    cout << value << " dup" << endl;
                }
            }

        }
    }


    void preOrderHelper(TreeNode<NODETYPE>* ptr) const {
        if (ptr != nullptr) {
            cout << ptr->data << " ";
            preOrderHelper(ptr->leftPtr);
            preOrderHelper(ptr->rightPtr);
        }
    }

    void inOrderHelper(TreeNode<NODETYPE>* ptr) const {
        if (ptr != nullptr) {
            inOrderHelper(ptr->leftPtr);
            cout << ptr->data << " ";
            inOrderHelper(ptr->rightPtr);
        }
    }

    void postOrderHelper(TreeNode<NODETYPE>* ptr) const {
        if (ptr != nullptr) {
            postOrderHelper(ptr->leftPtr);
            postOrderHelper(ptr->rightPtr);
            cout << ptr->data << " ";
        }

    }


};


#endif //BASE_CPP_TREE_H

TestTree.cpp

#include <iostream>
#include <iomanip>
#include "Tree.h"

using namespace std;

int main() {
    Tree<int> intTree;
    cout << "Enter 10 integer values:\n";

    for (int i{0}; i < 10; ++i){
        int intValue = 0;
        cin >> intValue;
        intTree.insertNode(intValue);
    }

    cout << "\nPreorder traversal\n";
    intTree.preOrderTraversal();

    cout << "\nInorder traversal\n";
    intTree.inOrderTraversal();

    cout << "\nPostorder traversal\n";
    intTree.postOrderTraversal();


}

/*
(base) ➜  build ./bin/list_demo 
Enter 10 integer values:
50
25
75
12
33
67
88
6
13
68

Preorder traversal
50 25 12 6 13 33 75 67 68 88 
Inorder traversal
6 12 13 25 33 50 67 68 75 88 
Postorder traversal
6 13 12 33 25 68 67 88 75 50 %  
 * 
 */

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值