数据结构-C++实现(二):单向链表

和数组不同,链表的数据结构内部多了一个指针指针下一个位置,使得在链表中插入删除特定位置的元素效率很高,代码实现依旧分为三个部分,抽象类LinearList.h,模板类chain.h以及main函数源文件。

废话不多说,我们看代码,这次LinearList.h抽象类里面多了两个成员函数一个是push_back(),一个是clear():

//
// Created by djf on 2016/12/18 0018.
//

#ifndef INC_01_ARRAYLIST_LINEARLIST_H
#define INC_01_ARRAYLIST_LINEARLIST_H

#include 
   
   
    
    
template 
    
    
     
     
class LinearList {
public:
    virtual ~LinearList() {};
    virtual bool empty() const = 0;
    virtual int size() const = 0;
    virtual T& get(int index) const = 0;
    virtual int indexof(const T& theElement) const = 0;//first pos
    virtual void erase(int index) = 0;
    virtual void insert(int index, const T& theElement) = 0;
    virtual void output(std::ostream& out) const = 0;
    //extend
    virtual void clear() = 0;
    virtual void push_back(const T& theElement)  = 0;
};


#endif //INC_01_ARRAYLIST_LINEARLIST_H
    
    
   
   
然后是chain.h,单向链表的模板类:

//
// Created by djf on 2016/12/20 0020.
//

#ifndef INC_02_CHAIN_CHAIN_H
#define INC_02_CHAIN_CHAIN_H

#include "LinearList.h"
using namespace std;
template 
   
   
    
    
struct chainNode{
    //data
    T element;
    chainNode
    
    
     
      *next;
    //method
    chainNode() {}
    chainNode(const T& e) { this->element=e;}
    chainNode(const T& e, chainNode
     
     
      
      * n) { this->element=e;this->next=n;}
};

template 
      
      
       
       
class chain: public LinearList
       
       
         { public: //one direction iterator class iterator{ public: // typedefs required by C++ for a forward iterator typedef forward_iterator_tag iterator_category; typedef T value_type; typedef ptrdiff_t difference_type; typedef T* pointer; typedef T& reference; //construct iterator(chainNode 
        
          * theNode = nullptr) { node = theNode;} //operator T& operator*() const { return node->element;} T* operator&() const { return &node->element;} iterator& operator++() { node = node->next;return *this;} iterator operator++(int) { iterator old = *this; node = node->next; return old;} bool operator==(const iterator rhl) const { return node == rhl.node;} bool operator!=(const iterator rhl) const { return node != rhl.node;} //other protected: chainNode 
         
           * node; }; public: //consturct copy destory chain(int initCapacity=10); chain(const chain 
          
            &); ~chain(); //ADT method from LinearList.h bool empty() const override { return listSize==0;}; int size() const override { return listSize;} T& get(int index) const override; int indexof(const T&) const override; void erase(int index) override; void insert(int index,const T& theElement) override; void output(ostream& out) const override; void push_back(const T& theElement) override ; void clear() override ; //other void removeRange(int fromIndex,int toIndex); int lastIndexOf(const T& theElement); T& operator[](int index) const; void reverse(); protected: void checkIndex(int index) const; chainNode 
           
             * headNode; int listSize; }; template 
            
              void chain 
             
               ::removeRange(int fromIndex, int toIndex) { checkIndex(fromIndex);checkIndex(toIndex); if(toIndex 
              
                * p = headNode; if(fromIndex!=0) { chainNode 
               
                 * q; for(int i = 0;i 
                
                  next; else { q = p->next; p->next = q->next; delete q; } } } else { for(int i = 0;i<=toIndex;++i) { headNode = headNode->next; delete p; p = headNode; } } } template 
                 
                   chain 
                  
                    ::chain(int initCapacity) { //chain中无capacity,这么写为了和LinearList兼容 if(initCapacity<1) cerr << "----!initSize must be >=1 !----"; listSize = 0; headNode = nullptr; } template 
                   
                     chain 
                    
                      ::chain(const chain 
                     
                       & theList) { listSize = theList.listSize; if(listSize==0) { headNode = nullptr; return; } chainNode 
                      
                        * sourceNode = theList.headNode; headNode = new chainNode 
                       
                         (sourceNode->element); sourceNode = sourceNode->next; chainNode 
                        
                          * targetNode = headNode; while(sourceNode!= nullptr) { targetNode->next = new chainNode 
                         
                           (sourceNode->element); sourceNode = sourceNode->next; targetNode = targetNode->next; } targetNode->next = nullptr; } template 
                          
                            chain 
                           
                             ::~chain() { wsnippet_file_0hile(headNode!= nullptr) { chainNode 
                            
                              * nextNode = headNode->next; delete headNode; headNode = nextNode; } } template 
                             
                               T &chain 
                              
                                ::get(int index) const { checkIndex(index); chainNode 
                               
                                 * currNode = headNode; for(int i=0;i 
                                
                                  next; return currNode->element; } template 
                                 
                                   void chain 
                                  
                                    ::checkIndex(int index) const { if(index<0 || index>=listSize) { cerr << "----! index outrange !----" << endl; return; } } template 
                                   
                                     int chain 
                                    
                                      ::indexof(const T & theElement) const { chainNode 
                                     
                                       * currNode = headNode; for(int i = 0;i 
                                      
                                        element==theElement) return i; currNode = currNode->next; } return -1; } template 
                                       
                                         void chain 
                                        
                                          ::erase(int index) { checkIndex(index); chainNode 
                                         
                                           * deleteNode; if(index==0) { deleteNode = headNode; headNode = headNode->next; } else { chainNode 
                                          
                                            *p = headNode; for(int i=0;i 
                                           
                                             next; deleteNode = p->next; p->next = p->next->next; } --listSize; delete deleteNode; } template 
                                            
                                              void chain 
                                             
                                               ::insert(int index, const T &theElement) { if(index<0 || index>listSize) { cerr << "---! insert index error !----" << endl; return; } if(index ==0) { headNode = new chainNode 
                                              
                                                (theElement,headNode); } else { chainNode 
                                               
                                                 *p = headNode; for (int i = 0; i < index - 1; ++i) p = p->next; p->next = new chainNode 
                                                
                                                  (theElement, p->next); } listSize++; } template 
                                                 
                                                   void chain 
                                                  
                                                    ::output(ostream &out) const { for(chainNode 
                                                   
                                                     * p = headNode;p != nullptr;p=p->next) out << p->element << " "; } template 
                                                    
                                                      void chain 
                                                     
                                                       ::push_back(const T &theElement) { chainNode 
                                                      
                                                        * currNode = headNode; for(int i=0;i 
                                                       
                                                         next; currNode->next = new chainNode 
                                                        
                                                          (theElement, nullptr); ++listSize; } template 
                                                         
                                                           void chain 
                                                          
                                                            ::clear() { chainNode 
                                                           
                                                             * p; while(headNode!= nullptr) { p = headNode->next; delete headNode; headNode = p; } listSize = 0; } template 
                                                            
                                                              int chain 
                                                             
                                                               ::lastIndexOf(const T& theElement) { int pos = -1;int i = 0; chainNode 
                                                              
                                                                * p = headNode; while (p != nullptr) { if (p->element == theElement) pos = i; else { ++i; p = p->next; } } } template 
                                                               
                                                                 T& chain 
                                                                
                                                                  ::operator[](int index) const { checkIndex(index); chainNode 
                                                                 
                                                                   * currNode = headNode; for(int i = 0;i 
                                                                  
                                                                    next; return currNode->element; } template 
                                                                   
                                                                     void chain 
                                                                    
                                                                      ::reverse() { if(listSize==0 || listSize==1) return; else if(listSize == 2) { chainNode 
                                                                     
                                                                       * p = headNode; headNode = headNode->next; headNode->next = p; p->next = nullptr; } else { chainNode 
                                                                      
                                                                        * p = headNode; chainNode 
                                                                       
                                                                         * q = headNode->next; chainNode 
                                                                        
                                                                          * r = headNode->next->next; headNode->next = nullptr; while(r->next != nullptr) { q->next = p; p = q; q = r; r = r->next; } q->next = p; r->next = q; headNode = r; } } template 
                                                                         
                                                                           ostream& operator<<(ostream& out, const chain 
                                                                          
                                                                            &a) { a.output(out); return out; } #endif //INC_02_CHAIN_CHAIN_H 
                                                                           
                                                                          
                                                                         
                                                                        
                                                                       
                                                                      
                                                                     
                                                                    
                                                                   
                                                                  
                                                                 
                                                                
                                                               
                                                              
                                                             
                                                            
                                                           
                                                          
                                                         
                                                        
                                                       
                                                      
                                                     
                                                    
                                                   
                                                  
                                                 
                                                
                                               
                                              
                                             
                                            
                                           
                                          
                                         
                                        
                                       
                                      
                                     
                                    
                                   
                                  
                                 
                                
                               
                              
                             
                            
                           
                          
                         
                        
                       
                      
                     
                    
                   
                  
                 
                
               
              
             
            
           
          
         
       
      
      
     
     
    
    
   
   
随便写的测试:

#include <iostream>
#include "chain.h"
int main()
{
    chain<int> ic;
    ic.insert(0,1);ic.insert(0,2);ic.push_back(3);ic.push_back(4);
    chain<int> ic1(ic);ic1.reverse();
    cout << ic1 << endl;
    return 0;
}
我发现写这个还是很锻炼人的,一个完善的数据结构轻轻松松几百行代码,每天一发,感觉很酸爽,C++简直写上瘾。

不废话了,我们回归头来看看链表的头文件里都定义了啥:

chainNode类定义了节点类,包含数据成员以及指向下一个节点的指针。包含构造、拷贝以及析构函数。

chan类继承自LinearList抽象类,包含节点类的成员变量,以及一个嵌套类iterator。

成员函数分为几个部分,首先是构造、拷贝以及析构函数,值得注意的是在构造函数中有一个参数initCapacity,实际是无作用的,仅仅为了和之前的ArrayList一致。

然后是继承自抽象类的方法,和ArrayList中的区别不大。

最后是我做的几个习题,void removeRange(int fromIndex,int toIndex)的作用是将参数限定范围内的节点删除的操作。int lastIndexOf(const T& theElement)是返回与函数参数相等的最后一个位置的索引。T& operator[](int index) const 是对[]运算符进行重载,返回指定索引的节点的数据的引用。void reverse()是将整个链表进行反转的操作,要求不开辟多余的空间。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以帮你解答这个问题。 首先,让我们来了解一下约瑟夫问题的背景。约瑟夫问题是一个经典的问题,据传是由古代历史学家约瑟夫斯(Josephus)提出的。问题的具体描述如下: 有n个人围成一圈,从第一个人开始报数,报到m的人出圈,剩下的人继续从1开始报数,直到剩下最后一个人。求出最后一个出圈的人的编号。 为了解决这个问题,我们可以使用单向循环链表实现。下面是一个简单的C++单向循环链表实现,包含了三个文件:Node.h、List.h和List.cpp。 首先是Node.h文件,用来定义节点类: ```cpp // Node.h #ifndef NODE_H #define NODE_H class Node { public: int data; Node* next; Node(int data) { this->data = data; next = nullptr; } }; #endif ``` 然后是List.h文件,用来定义链表类: ```cpp // List.h #ifndef LIST_H #define LIST_H #include "Node.h" class List { public: List(); ~List(); void insert(int data); void remove(Node* node); Node* getHead(); Node* getNext(Node* node); private: Node* head; }; #endif ``` 最后是List.cpp文件,用来实现链表类的方法: ```cpp // List.cpp #include "List.h" List::List() { head = nullptr; } List::~List() { Node* curr = head; while (curr != nullptr) { Node* temp = curr; curr = curr->next; delete temp; } } void List::insert(int data) { Node* node = new Node(data); if (head == nullptr) { head = node; head->next = head; } else { Node* curr = head; while (curr->next != head) { curr = curr->next; } curr->next = node; node->next = head; } } void List::remove(Node* node) { Node* curr = head; if (node == head) { head = head->next; } else { while (curr->next != node) { curr = curr->next; } curr->next = node->next; } delete node; } Node* List::getHead() { return head; } Node* List::getNext(Node* node) { return node->next; } ``` 现在我们就可以使用这个单向循环链表来解决约瑟夫问题了。下面是一个简单的解决方案: ```cpp #include <iostream> #include "List.h" int josephus(int n, int m) { List list; for (int i = 1; i <= n; i++) { list.insert(i); } Node* curr = list.getHead(); while (n > 1) { for (int i = 1; i < m; i++) { curr = list.getNext(curr); } Node* temp = curr; curr = list.getNext(curr); list.remove(temp); n--; } return list.getHead()->data; } int main() { int n = 5; int m = 3; int result = josephus(n, m); std::cout << "The last person is " << result << std::endl; return 0; } ``` 这个程序将输出: ``` The last person is 4 ``` 这就是使用C++单向循环链表解决约瑟夫问题的一个简单的例子。希望能对你有所帮助!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值