c++中的单向链表写法:实现增删查改、构造函数、运算符重载、析构函数等。

建立头文件SList.h

#pragma oncetypedef int DataType;
//SList要访问SListNode,可以通过友元函数实现,友元函数在被访问的类中
class SListNode
{friend class SList;//友元函数
public:SListNode(const DataType x):_data(x), _next(NULL){}
private:SListNode* _next;DataType _data;
};class SList
{
public:SList():_head(NULL), _tail(NULL){}//深拷贝SList(const SList& s):_head(NULL), _tail(NULL){SListNode* cur = s._head;while (cur){this->PushBack(cur->_data);cur = cur->_next;}}深拷贝的传统写法//SList& operator=(const SList& s)//{// if (this != &s)//  {//     Clear();//      SListNode* cur = s._head;//        while (cur)//       {//         this->PushBack(cur->_data);//         cur = cur->_next;//     }// }// return *this;//}//深拷贝的现代写法SList& operator=(SList& s){swap(_head, s._head);swap(_tail, s._tail);return *this;}~SList(){Clear();}
public:void Clear();void PushBack(DataType x);void PopBack();void PushFront(DataType x);void PopFront();//void Insert(size_t pos,DataType x);void Insert(SListNode* pos, DataType x);void Erase(SListNode* pos);SListNode* Find(DataType x);void PrintSList();
private:SListNode* _head;SListNode* _tail;
};

各函数的实现

#include<iostream>
using namespace std;#include"SList.h"
#include<assert.h>void SList::Clear()
{SListNode* cur = _head;while (cur){SListNode* del = cur;cur = cur->_next;delete del;del = NULL;}
}void SList::PrintSList()//打印链表
{SListNode* cur = _head;while (cur){cout << cur->_data << "->";cur = cur->_next;}cout << "NULL" << endl;
}void SList::PushBack(DataType x)//尾插
{if (NULL == _head){_head = new SListNode(x);//开辟一个值为x的新结点_tail = _head;}else{//SListNode* cur;//cur->_data = x;//_tail->_next = cur;//_tail = cur;_tail->_next= new SListNode(x);_tail = _tail->_next;}
}void SList::PopBack()//尾删
{if (NULL == _head){cout << "SList is empty!" << endl;}else if (_head == _tail){delete _head;_head = _tail = NULL;}else{SListNode* cur = _head;//找到要删除尾节点的前一个节点curwhile (cur->_next->_next){cur = cur->_next;}delete cur->_next;cur->_next = NULL;_tail = cur;}
}void SList::PushFront(DataType x)//头插
{SListNode* tmp = _head;_head=new SListNode(x);_head->_next = tmp;}void SList::PopFront()//头删
{if (NULL == _head){cout << "SList is empty!" << endl;}else if (NULL == _head->_next){delete _head;_head = NULL;//delete后要将指针设空,否则产生野指针}else{SListNode* tmp = _head->_next;delete _head; _head = tmp;}
}//void SList::Insert(size_t pos, DataType x)
//{
//  assert(pos);
//  SListNode* tmp = _head;
//  pos -= 1;
//  while (--pos)
//  {
//      tmp = tmp->_next;
//  }
//  if (NULL == tmp)
//      SList::PushBack(x);
//  else
//  {
//      SListNode* next = tmp->_next;
//      SListNode* cur = new SListNode(x);
//      tmp->_next = cur;
//      cur->_next = next;
//  }
//}void SList::Insert(SListNode* pos, DataType x)指定位置处插入x
{assert(pos);SListNode* tmp = _head;while (tmp){if (NULL == tmp->_next)SList::PushFront(x);else if (pos == tmp->_next){SListNode* cur = new SListNode(x);cur->_next= tmp->_next;tmp->_next = cur;return;//注意结束循环}tmp = tmp->_next;}
}void SList::Erase(SListNode* pos)
{assert(pos);SListNode* tmp = _head;while (tmp){if (NULL == tmp->_next)SList::PopFront();else if (pos == tmp->_next){SListNode* cur = tmp->_next->_next;delete tmp->_next;tmp->_next = NULL;tmp->_next = cur;return;//注意结束循环}tmp = tmp->_next;}
}SListNode* SList::Find(DataType x)
{SListNode* cur = _head;while (cur){if (x == cur->_data){return cur;}cur = cur->_next;}return NULL;
}

各操作的测试用例

void Test1()
{//尾插尾删SList S;S.PushBack(1);S.PushBack(2);S.PushBack(3);S.PushBack(4);S.PrintSList();S.PopBack();S.PrintSList();//S.PopBack();//S.PopBack();//S.PrintSList();//S.PopBack();//S.PopBack();//S.PopBack();SList S1(S);S1.PrintSList();SList S2;S2 = S;S2.PrintSList();
}void Test2()
{//头插头删SList S;S.PushFront(1);S.PushFront(2);S.PushFront(3);S.PushFront(4);S.PrintSList();S.PopFront();S.PrintSList();S.PopFront();S.PopFront();S.PopFront();S.PrintSList();S.PopFront();
}void Test3()
{//指定位置插入某数,查找某数SList S;S.PushBack(1);S.PushBack(2);S.PushBack(4);S.PushBack(5);S.PrintSList();//S.Insert(3, 3);SListNode* p = S.Find(4);S.Insert(p, 3);S.PrintSList();
}void Test4()
{//删除某结点SList S;S.PushBack(1);S.PushBack(2);S.PushBack(3);S.PushBack(10);S.PushBack(4);S.PushBack(5);S.PrintSList();SListNode* p = S.Find(10);S.Erase(p);S.PrintSList();
}

友元函数

在实现类之间数据共享时,减少系统开销,提高效率。如果类A中的函数要访问类B中的成员(例如:智能指针类的实现),那么类A中该函数要是类B的友元函数。具体来说:为了使其他类的成员函数直接访问该类的私有变量。即:允许外面的类或函数去访问类的私有变量和保护变量,从而使两个类共享同一函数。

实际上具体大概有下面两种情况需要使用友元函数:

(1)运算符重载的某些场合需要使用友元。

(2)两个类要共享数据的时候。

1.1使用友元函数的优缺点

优点:能够提高效率,表达简单、清晰。

缺点:友元函数破环了封装机制,尽量不使用成员函数,除非不得已的情况下才使用友元函数。

1.2友元函数的参数

因为友元函数没有this指针,则参数要有三种情况:

(1) 要访问非static成员时,需要对象做参数;

(2)要访问static成员或全局变量时,则不需要对象做参数;

(3)如果做参数的对象是全局对象,则不需要对象做参数;

1.3友元函数的位置

因为友元函数是类外的函数,所以它的声明可以放在类的私有段或公有段且没有区别。

1.4友元函数的调用

可以直接调用友元函数,不需要通过对象或指针

友元函数和类的成员函数的区别

成员函数有this指针,而友元函数没有this指针。

友元函数是不能被继承的,就像父亲的朋友未必是儿子的朋友。

转载于:https://blog.51cto.com/luoyafei/1748574

c++单链表【构造函数、运算符重载、析构函数、增删查改等】相关推荐

  1. 单链表的增删查改等基本操作C++实现

    单链表的初始化.增删查改.遍历一次找中间结点.删除一个无头单链表的非尾结点(不给头结点) #include<stdio.h> #include<stdlib.h> #inclu ...

  2. (不带头结点的)单链表增删查改,逆置单链表(两种方法),求两个单链表的第一个公共结点,合并两个单链表,单循环链表中判断第一个入环点,约瑟夫环

    补充了每个算法的基本思想,并且画了思路图,源代码都经过调试成功 1.SlistNode.c文件 (1) (不带头结点的)单链表增删查改 #include "SlistNode.h" ...

  3. 数据结构之单链表的增删查改等操作画图详解

    单链表 文章目录 单链表 链表的概念及其结构 概念 结构 链表的实现 开辟一个新结点 链表的销毁 打印链表 单链表的尾插 单链表的头插 单链表的头删 单链表的尾删 找到单链表中的一个结点 在pos位置 ...

  4. 【顺序表和链表】实现增删查改数据结构 OJ题编程

    目录 线性表 一.顺序表 1.使用顺序表MyArrayList增删查改 MyArrayList.java TestDemo.java 二.链表 1.带头 / 不带头 循环 / 非循环 2.创建链表并访 ...

  5. 【数据结构】链表:带头双向循环链表的增删查改

    本篇要分享的内容是带头双向链表,以下为本片目录 目录 一.链表的所有结构 二.带头双向链表 2.1尾部插入 2.2哨兵位的初始化 2.3头部插入 2.4 打印链表 2.5尾部删除 2.6头部删除 2. ...

  6. python单链表操作_单链表的创建、增删改查等操作(Python实现)

    单链表的创建.增删改查等操作(Python实现) # 单链表 class Node: def __init__(self, elem): self.elem = elem self.next = No ...

  7. Java——链表的增删查改

    [基础学习] 链表的增删查改 注意:所有链表都先需要判断是否为null <1>链表的增 有三种方法,分别为:头插法,尾插法,任意节点位置插法 1.头插法 2.尾插法 3.任意节点位置插法 ...

  8. 单链表的实现与增删改查

    单链表的实现与CRUD 单链表的实现与增删改查 链表实现 结果: Hero{id=1, name='dog1', otherName='aadog1'} Hero{id=2, name='dog2', ...

  9. 【C++ 语言】vector 容器 ( 容器分类 | vector 声明 | vector 初始化 | vector 容器元素增删查改 )

    文章目录 序列式容器 vector 简介 vector ( 向量 ) 头文件 vector ( 向量 ) 声明及初始化 vector ( 向量 ) 添加元素 vector ( 向量 ) 查询元素 ve ...

最新文章

  1. AWS Storage Gateway 分类
  2. C# ICSharpCode.SharpZipLib.Zip 的使用
  3. Compose 手势事件:防止重复点击,双击,长按,全局触摸隐藏键盘
  4. python 读写函数
  5. Android布局属性详解之RelativeLayout
  6. linux 虚拟文件系统 源码,Linux内核源代码情状分析-虚拟文件系统
  7. ubuntu下c 调用java_ubuntu下使用JNI Java调用C++的例子
  8. Spring MVC 关于分页的简单实现
  9. 9. Linux 磁盘与文件管理系统(inode 目录)
  10. android谷歌打印插件下载地址,谷歌浏览器打印插件:Print Plus
  11. C++学习(四六六)Multiple parse contexts are available for this file
  12. 线性稳压芯片的优势及注意事项
  13. Falsy Bouncer(算法)
  14. 完美解决异常问题UnicodeEncodeError: ‘ascii‘ codec can‘t encode characters in position 0-7: ordinal not in ra
  15. 人形机器人视觉处理——走迷宫
  16. 游戏引擎除了开发游戏还能做什么?
  17. 突破!龙芯国产域名服务器+红枫2.0 底层技术问题再进一步
  18. Android Studio 使用Vuforia(高通)开发AR
  19. java毕业设计艾灸减肥管理网站Mybatis+系统+数据库+调试部署
  20. python是一种跨平台开源免费的高级动态编程语言_Python是一种跨平台、开源、免费的高级动态编程语言。...

热门文章

  1. 剑指offer(65)矩阵中的路径
  2. 微信分享无响应的解决
  3. Retina时代的前端视觉优化
  4. HTML元素title里面如何换行
  5. js高级 — ES6
  6. 在mac上安装gitlab
  7. Python并发编程—进程
  8. MySQL触发器(转载)
  9. Matlab之rand(), randn(), randi()函数的使用方法
  10. python---重点(设计模式)