c++数据结构---单链表

118 阅读3分钟

 单链表的概念

这里每个节点存储:自己的数据元素和指向其后继结点的指针 
正是这种设计反映了结点之间的关系

这里的头结点的设计只是为了插入和删除操作的方便,比如在第一个元素前插入结点,如果没有头指针,那么从实现来说很困难。

而且链表最后一个元素如果没有后继,其后继结点的指针置为空

单链表类的设计

  • 首先需要一个**结点类****----**里面存储自己的元素数据和后继结点的指针
  • 对于链表类而言**----**只需存储用于遍历结点的头指针以及为了计算链表长度方便而设计的curLength
private:
    struct node{
        elemType data;
        node* next;
    };
    node* head;
    int curLength;

几个设计:

  • node设计成结构而非类,是因为链表函数需要频繁访问其存储的数据,struct的成员默认共有,而class成员默认私有
  • 由于struct成员和类一样也需要初始化,从而要补充构造函数和析构函数
  • 由于插入和删除操作要找第i个结点的位置,为了方便起见,设计一个私有成员函数move(i) 
private:
    struct node{
        elemType data;
        node* next;
        //构造函数
        node(const elemType& x,node* n=NULL){
            data=x;
            next=n;
        }
        node():next(NULL){}
        //析构函数
        ~node(){};
    };
    node* head;
    int curLength;
    //返回指向第i个结点的指针
    node* move(int i)const;

 链表类的构造和析构函数

 sLinklist(){
        head=new node;//创建新节点,调用了无参构造node():next(NULL){}
        curLength=0;
    }
    ~sLinklist(){
        clear();//clear操作会delete所有结点数据
        delete head;//
    }

 clear()

//clear()
template<class elemType>
void sLinklist<elemType>::clear(){
    node* p=head->next;//要销毁结点
    node* q;//辅助结点,记录下一个销毁位置
    head->next=NULL;//clear结果
    while(p!=NULL){
        q=p->next;
        delete p;
        p=q;
    }
    curLength=0;
}

两步:

clear结果-----head->next=NULL;    curLength=0;

delete链表已有数据结点:

双指针,p要销毁的节点,必须是head->next,q记录销毁的下一个位置

insert(i,x)

首先实现move(i)

template<class elemType>
sLinklist<elemType>::node* sLinklist<elemType>::move(int i)const{
    node* p=head;
    while(i-->=0) p=p->next;
    return p;
}

 注意move是私有成员函数,其类型前也要加上---sLinklist<elemType<::

 要找到第i个位置的元素,头指针要向后移动i次.注意和数组一样从0开始

 注意:vs的gcc在编译时候需要在sLinklist前加上“typename”

remove(i)

//remove(i)
template<class elemType>
void sLinklist<elemType>::remove(int i){
    node* p=move(i-1);
    node* q=p->next;
    p->next=q->next;
    delete q;
    --curLength;
}

 visit(i);search(x);traverse()

//search(x)
template<class elemType>
int sLinklist<elemType>::search(const elemType& x) const{
    node* p=head->next;
    int i=0;
    while(p&&p->data!=x){
        p=p->next;
        i++;
    }
    if(p==NULL){
        return -1;
    }
    else
        return i;
}
//visit(i)
template<class elemType>
 elemType sLinklist<elemType>::visit(int i) const{
       node* p=move(i);
       return p->data;
 }
//traverse()
#include<iostream>
using namespace std;
template<class elemType>
void sLinklist<elemType>::traverse() const{
    node *p=head->next;
      while(p){
         cout<<p->data<<",";
         p=p->next;
      }
      cout<<endl;
}


总程序:

list.h

#ifndef MY_list
#define MY_list
template<class elemType>
class list{
    public:
    virtual ~list(){};
    virtual void clear()=0;
    virtual int listLength() const=0;
    virtual void insert(int i,const elemType& x)=0;
    virtual void remove(int i)=0;
    virtual int search(const elemType& x) const=0;
    virtual elemType visit(int i) const=0;
    virtual void traverse() const=0;
};
#include"sLinklist.h"
#endif

sLinklist.h

#ifndef MY_slinklist
#define MY_slinklist
#include"list.h"
template<class elemType>
class sLinklist:public list<elemType>{
private:
    struct node{//和类一样加;
        elemType data;
        node* next;
        //构造函数
        node(const elemType& x,node* n=NULL){
            data=x;
            next=n;
        }
        node():next(NULL){}
        //析构函数
        ~node(){};
    };
    node* head;
    int curLength;
    //返回指向第i个结点的指针
    node* move(int i) const;
public:
    sLinklist(){
        head=new node;//创建新节点,调用了无参构造node():next(NULL){}
        curLength=0;
    }
    ~sLinklist(){
        clear();//clear操作会delete所有结点数据
        delete head;//
    }
    void clear();
    int listLength() const{
        return curLength;
    }
    void insert(int i,const elemType& x);
    void remove(int i);
    int search(const elemType& x) const;
    elemType visit(int i) const;
    void traverse() const;
};
//clear()
template<class elemType>
void sLinklist<elemType>::clear(){
    node* p=head->next;//要销毁结点
    node* q;//辅助结点,记录下一个销毁位置
    head->next=NULL;//clear结果
    while(p!=NULL){
        q=p->next;
        delete p;
        p=q;
    }
    curLength=0;
}
//move(i)
template<class elemType>
typename sLinklist<elemType>::node * sLinklist<elemType>::move(int i) const {
    node* p=head;
    while(i-->=0) p=p->next;
    return p;
}
//insert(i,x)
template<class elemType>
void sLinklist<elemType>::insert(int i,const elemType& x){
      node* pos=move(i-1);
      pos->next=new node(x,pos->next);//申请结点并把它next链入链表
      ++curLength;
 }
//remove(i)
template<class elemType>
void sLinklist<elemType>::remove(int i){
    node* p=move(i-1);
    node* q=p->next;
    p->next=q->next;
    delete q;
    --curLength;
}
//search(x)
template<class elemType>
int sLinklist<elemType>::search(const elemType& x) const{
    node* p=head->next;
    int i=0;
    while(p&&p->data!=x){
        p=p->next;
        i++;
    }
    if(p==NULL){
        return -1;
    }
    else
        return i;
}
//visit(i)
template<class elemType>
 elemType sLinklist<elemType>::visit(int i) const{
       node* p=move(i);
       return p->data;
 }
//traverse()
#include<iostream>
using namespace std;
template<class elemType>
void sLinklist<elemType>::traverse() const{
    node *p=head->next;
      while(p){
         cout<<p->data<<",";
         p=p->next;
      }
      cout<<endl;
}
#endif

maintest.cpp

#include<iostream>
#include"list.h"
using namespace std;
int main(){
    sLinklist<int> slink;
    slink.insert(0,7);
    slink.insert(1,17);
    slink.insert(2,8);
    slink.insert(3,19);
    slink.insert(4,9);
    slink.traverse();
    slink.remove(2);
    slink.traverse();
    cout<<slink.listLength()<<endl;
    cout<<slink.search(17)<<endl;
    cout<<slink.visit(2);
    return 0;
}

\