c++ 数据结构 链表类(详解)

包含链表类的一些基本操作。

大二数据结构课后题,之后会慢慢更新更多操作。

还有许多方法写法不够简洁完善,会慢慢更新

完整代码在最后

首先是类的设计:

typedef int ElementType;

class LinkList

{

private:

 class Node

 {

    public:

    ElementType data;

    Node * next;

    Node():next(0) {}//默认构造函数

    Node(ElementType dataValue):data(dataValue), next(0){}//显值构造函数

 };

public:

 typedef Node * NodePointer;

 LinkList(){mySize = 0;first = 0;}   //构造函数

 LinkList(const LinkList & origList);//复制构造函数

 ~LinkList();  //析构函数

 //void release();

 const LinkList & operator=(const LinkList & rightSide); //赋值运算符重载

 bool empty();  //链表判空

 void insert(ElementType dataVal, int index); //在链表指定位置插入节点

 void erase(int index);  //删除链表中指定位置的节点

 NodePointer search(ElementType dataVal); //查找链表中指定值的节点

 void display(ostream & out) const;//输出链表节点值

 void input(istream & in,int n);

 int nodeCount();   //计算节点个数

 void reverse();      //链表反转,即尾结点变为链表第一个节点

 bool ascendingOrder();  //判断链表是否为升序排列

 void ListMerge(LinkList & templist);//链表B合并到链表A末尾

 void MergeList(LinkList & listA,LinkList & listB);//链表A和链表B合并到链表C上

 ElementType get(NodePointer temp); 

private:

 NodePointer first; //指向第一个节点的指针

 int mySize; //节点的数目

};

方法的实现:

1.拷贝构造函数:

LinkList::LinkList(const LinkList & origList){//拷贝函数
   mySize = origList.mySize;
   first = 0;
   if(mySize == 0)return;
   NodePointer origPtr,lastPtr;
   first = new Node(origList.first->data);
   lastPtr = first;
   origPtr = origList.first->next;
   while(origPtr != 0){
      lastPtr->next = new Node(origPtr->data);
      origPtr = origPtr->next;
      lastPtr = lastPtr->next;
   }

}

LinkList::~LinkList(){//析构函数
   NodePointer prev = first,ptr;
   while(prev != 0){
      ptr = prev->next;
      delete prev;
      prev = ptr;
   }
}

2.empty函数:

bool LinkList::empty(){//判断是否为空
   if(!mySize)return true;
   return false;
}

3.insert插入节点

void LinkList::insert(ElementType dataVal, int index){//在index位置插入dataVal
   if(index < 0 || index > mySize){
      cerr << "illegal to insert--" << index << endl;
      return; 
   }
   mySize++;
   NodePointer newPtr = new Node(dataVal),prePtr = first;
   if(index == 0){//插入到第一个位置
      newPtr->next = first;
      first = newPtr;
   }
   else{//若列表不为空
      for(int i = 0;i < index-1;i++){//不断移动插入,移动index-1次,即插入到所需位置
         prePtr = prePtr->next;
      }
      newPtr->next = prePtr->next; 
      prePtr->next = newPtr;
   }
}

4.erase 删除节点

void LinkList::erase(int index){//删除第index个节点
   if(index < 0 || index >= mySize || empty()){
      cerr << "illegal to erase--" << index << endl;
      return; 
   }
   mySize--;
   NodePointer prePtr = first;
   if(mySize==1){//若只有一个节点
      first = 0;
   }
   else{
      if(index == 0){
         first = prePtr->next;
         delete prePtr;
         return;
      }
      for(int i = 1;i < index-1;i++)//删除index节点,只需移动到index-1位置
        prePtr = prePtr->next;
      prePtr->next = prePtr->next->next;//将prePtr的next连接至下下个节点
   }
}

5.查找指定数据的指定节点(注意最前面NodePointer要声明是Linklist里的)

LinkList::NodePointer LinkList::search(ElementType dataVal){//查找链表中指定值的节点
   if(empty()){
      cerr << "illegal to search--" << dataVal << endl;
   }
   NodePointer prePtr = first;
   while(prePtr->data != dataVal)
      prePtr = prePtr->next;
   if(prePtr==0)
      cerr << "illegal to search--" << dataVal << endl;
   else
      return prePtr;
}

6.display输出链表节点值,与输出重载相结合使用

void LinkList::display(ostream & out) const{//输出链表节点值
   NodePointer prePtr = first;
   while(prePtr != 0){
      out<<prePtr->data<<" ";
      prePtr = prePtr->next;
   }
}

7.input输入流函数,与提取重载相结合使用

void LinkList::input(istream & in,int n){//输入链表节点值
   int mysize1 = 0;
   for(int i = 0;i < n;i++){
      cout<<"请输入第"<<i+1<<"个节点的数据:";
      ElementType x;
      in>>x;
      insert(x,mysize1);
   }
}

8.nodeCount计算共有几个节点

int LinkList::nodeCount(){   //计算节点个数
   return mySize;
}

9.reverse反转函数

void LinkList::reverse(){//链表反转,即尾结点变为链表第一个节点
   NodePointer old_head = first,new_head=0,temp;
   while(old_head){
      temp = old_head->next;
      old_head->next = new_head;
      new_head =old_head;
      old_head = temp;
   }
   first = new_head;
}

10.判断是否递增

bool LinkList::ascendingOrder(){//判断链表是否为升序排列
   NodePointer prePtr = first;
   while(prePtr->next != 0){
      if(prePtr->data > prePtr->next->data)return false;
      prePtr = prePtr->next;
   }
   return true;
}

11.把B合并进A,且B不变,两个指针同时递增,B中每个节点拷贝一个,防止B发生改变

void LinkList::ListMerge(LinkList & templist){//链表B合并到链表A末尾
   NodePointer prePtr = first;
   while(prePtr->next != 0)
      prePtr = prePtr->next;
   NodePointer prePtrB = templist.first;
   while(prePtrB != 0){
      this->mySize++;
      prePtr->next = new Node(prePtrB->data);
      prePtrB = prePtrB->next;
      prePtr = prePtr->next;
   }
}

12.把A,B合并,再接到C(本身)

void LinkList::MergeList(LinkList & listA,LinkList & listB){//链表A和链表B合并到链表C上
   listA.ListMerge(listB);
   this->ListMerge(listA);
}

13.get函数

ElementType LinkList::get(NodePointer temp){
   return temp->data;
}

14.插入运算符重载

ostream & operator<<(ostream & out, const LinkList &List){ //插入运算符重载(可选做)
   List.display(out);
   return out;
}

15.提取运算符重载

istream & operator>>(istream & in, LinkList &List){//提取运算符重载(可选做)
   cout<<"请输入链表节点的个数:";
   int N;
   cin >> N;
   List.input(in,N);
   return in;
}

16.赋值重载符:

LinkList const &LinkList::operator=(const LinkList &rightSide) //赋值运算符重载
{
    mySize = rightSide.mySize;
    first=0;
    NodePointer origPtr,lastPtr;
    first = new Node(rightSide.first->data);
    lastPtr = first;
    origPtr = rightSide.first->next;
    while (origPtr != 0)
    {
        lastPtr->next = new Node(origPtr->data);
        origPtr= origPtr->next;
        lastPtr = lastPtr->next;
    }
    return *this;
}

完整code(含测试):

#include<iostream>
using namespace std;
typedef int ElementType;

class LinkList

{

private:

 class Node

 {

    public:

    ElementType data;

    Node * next;

    Node():next(0) {}//默认构造函数

    Node(ElementType dataValue):data(dataValue), next(0){}//显值构造函数

 };

public:

 typedef Node * NodePointer;

 LinkList(){mySize = 0;first = 0;}   //构造函数

 LinkList(const LinkList & origList);//复制构造函数

 ~LinkList();  //析构函数

 //void release();

 const LinkList & operator=(const LinkList & rightSide); //赋值运算符重载

 bool empty();  //链表判空

 void insert(ElementType dataVal, int index); //在链表指定位置插入节点

 void erase(int index);  //删除链表中指定位置的节点

 NodePointer search(ElementType dataVal); //查找链表中指定值的节点

 void display(ostream & out) const;//输出链表节点值

 void input(istream & in,int n);

 int nodeCount();   //计算节点个数

 void reverse();      //链表反转,即尾结点变为链表第一个节点

 bool ascendingOrder();  //判断链表是否为升序排列

 void ListMerge(LinkList & templist);//链表B合并到链表A末尾

 void MergeList(LinkList & listA,LinkList & listB);//链表A和链表B合并到链表C上

 ElementType get(NodePointer temp); 

private:

 NodePointer first; //指向第一个节点的指针

 int mySize; //节点的数目

};

LinkList::LinkList(const LinkList & origList){//拷贝函数
   mySize = origList.mySize;
   first = 0;
   if(mySize == 0)return;
   NodePointer origPtr,lastPtr;
   first = new Node(origList.first->data);
   lastPtr = first;
   origPtr = origList.first->next;
   while(origPtr != 0){
      lastPtr->next = new Node(origPtr->data);
      origPtr = origPtr->next;
      lastPtr = lastPtr->next;
   }

}

LinkList::~LinkList(){//析构函数
   NodePointer prev = first,ptr;
   while(prev != 0){
      ptr = prev->next;
      delete prev;
      prev = ptr;
   }
}

bool LinkList::empty(){//判断是否为空
   if(!mySize)return true;
   return false;
}

LinkList const &LinkList::operator=(const LinkList &rightSide) //赋值运算符重载
{
    mySize = rightSide.mySize;
    first=0;
    NodePointer origPtr,lastPtr;
    first = new Node(rightSide.first->data);
    lastPtr = first;
    origPtr = rightSide.first->next;
    while (origPtr != 0)
    {
        lastPtr->next = new Node(origPtr->data);
        origPtr= origPtr->next;
        lastPtr = lastPtr->next;
    }
    return *this;
}
void LinkList::insert(ElementType dataVal, int index){//在index位置插入dataVal
   if(index < 0 || index > mySize){
      cerr << "illegal to insert--" << index << endl;
      return; 
   }
   mySize++;
   NodePointer newPtr = new Node(dataVal),prePtr = first;
   if(index == 0){//插入到第一个位置
      newPtr->next = first;
      first = newPtr;
   }
   else{//若列表不为空
      for(int i = 0;i < index-1;i++){//不断移动插入,移动index-1次,即插入到所需位置
         prePtr = prePtr->next;
      }
      newPtr->next = prePtr->next; 
      prePtr->next = newPtr;
   }
}

void LinkList::erase(int index){//删除第index个节点
   if(index < 0 || index >= mySize || empty()){
      cerr << "illegal to erase--" << index << endl;
      return; 
   }
   mySize--;
   NodePointer prePtr = first;
   if(mySize==1){//若只有一个节点
      first = 0;
   }
   else{
      if(index == 0){
         first = prePtr->next;
         delete prePtr;
         return;
      }
      for(int i = 1;i < index-1;i++)//删除index节点,只需移动到index-1位置
        prePtr = prePtr->next;
      prePtr->next = prePtr->next->next;//将prePtr的next连接至下下个节点
   }
}

LinkList::NodePointer LinkList::search(ElementType dataVal){//查找链表中指定值的节点
   if(empty()){
      cerr << "illegal to search--" << dataVal << endl;
   }
   NodePointer prePtr = first;
   while(prePtr->data != dataVal)
      prePtr = prePtr->next;
   if(prePtr==0)
      cerr << "illegal to search--" << dataVal << endl;
   else
      return prePtr;
}

void LinkList::display(ostream & out) const{//输出链表节点值
   NodePointer prePtr = first;
   while(prePtr != 0){
      out<<prePtr->data<<" ";
      prePtr = prePtr->next;
   }
}

void LinkList::input(istream & in,int n){//输入链表节点值
   int mysize1 = 0;
   for(int i = 0;i < n;i++){
      cout<<"请输入第"<<i+1<<"个节点的数据:";
      ElementType x;
      in>>x;
      insert(x,mysize1);
      mysize1++;
   }
}

int LinkList::nodeCount(){   //计算节点个数
   return mySize;
}

void LinkList::reverse(){//链表反转,即尾结点变为链表第一个节点
   NodePointer old_head = first,new_head=0,temp;
   while(old_head){
      temp = old_head->next;
      old_head->next = new_head;
      new_head =old_head;
      old_head = temp;
   }
   first = new_head;
}

bool LinkList::ascendingOrder(){//判断链表是否为升序排列
   NodePointer prePtr = first;
   while(prePtr->next != 0){
      if(prePtr->data > prePtr->next->data)return false;
      prePtr = prePtr->next;
   }
   return true;
}

void LinkList::ListMerge(LinkList & templist){//链表B合并到链表A末尾
   NodePointer prePtr = first;
   while(prePtr->next != 0)
      prePtr = prePtr->next;
   NodePointer prePtrB = templist.first;
   while(prePtrB != 0){
      this->mySize++;
      prePtr->next = new Node(prePtrB->data);
      prePtrB = prePtrB->next;
      prePtr = prePtr->next;
   }
}

void LinkList::MergeList(LinkList & listA,LinkList & listB){//链表A和链表B合并到链表C上
   listA.ListMerge(listB);
   this->ListMerge(listA);
}

ElementType LinkList::get(NodePointer temp){
   return temp->data;
}
ostream & operator<<(ostream & out, const LinkList &List){ //插入运算符重载(可选做)
   List.display(out);
   return out;
}

istream & operator>>(istream & in, LinkList &List){//提取运算符重载(可选做)
   cout<<"请输入链表节点的个数:";
   int N;
   cin >> N;
   List.input(in,N);
   return in;
}

int main(){
   LinkList l;
   LinkList l2;
   cin>>l;
   LinkList l1(l);
   l2 = l;
   cout<<l2<<endl;
   cout<<l<<endl;
   l.reverse();
   cout<<l<<endl;
   cout<<l.nodeCount()<<endl;
   l.ListMerge(l1);
   cout<<l<<endl;
   cout<<l.nodeCount()<<endl;
   l.erase(4);
   cout<<l<<endl;
   l.insert(10,7);
   cout<<l<<endl;
   if(l.ascendingOrder())cout<<"递增"<<endl;
   else cout<<"不递增"<<endl;
   if(l.empty())cout<<"空链表"<<endl;
   else cout<<"非空链表"<<endl;
   return 0;
}

  • 10
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值