#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <fstream>
#include <string> using namespace std; //类
class List
{
public:
//构造器初始化,生成头节点
List()
{
head = new Node;
head->next = NULL;
} //成员函数
void createList();
void insertList(int data);
void travelList(int chance);
void input();
int addNode();
void deleteData(int addNum);
void ifClear();
void clearList();
//重载下标
int operator[](int idx);
//重载+
friend List operator+(List& List_1, List& List_2);
//重载-
friend List operator-(List& List_1, List& List_2);
//重载<<
friend ostream& operator<<(ostream& os, List& list);
//重载>>
friend istream& operator>>(istream& is, List& list);
//冒泡排序
void bubbleSortList(List& list);
private:
//数据成员
struct Node
{
int data; //数据域
struct Node* next; //指针域 } *head;//头指针 int num;//链表元素个数
}; //头插法生成节点
void List::insertList(int data)
{
Node* cur = new Node; //插入数据
cur->data = data; //插入节点
cur->next = head->next;
head->next = cur;
} //调用insertList输入数据,生成链表
void List::input()
{
cout << "请输入链表数量长度:";
cin >> num;
srand(time(NULL));
for (int i = 0; i < num; i++)
{
insertList(rand() % 100);
}
} //任意位置插入节点
int List::addNode()
{
int d, idx; cout << "请输入你要插入的节点数据:";
cin >> d;
cout << "请输入你要插入的节点位置: ";
cin >> idx; Node* tp = NULL;
Node* link = head; //寻找插入位置
if (idx<1 || idx>num + 1)
{
cout << "操作非法" << endl;
return num;
}
else
{
for (int i = 0; i < idx; i++)
{
tp = link;
link = link->next;
} Node* cur = new Node;
tp->next = cur;
cur->data = d;
cur->next = link;
travelList(1);
return ++num;
}
} ofstream mycout1("D:/text1.txt");
ofstream mycout2("D:/text2.txt");
//遍历链表并将数据存入文件
void List::travelList(int chance)
{
Node* temp = head->next; //防止头指针地址改变
while (temp != NULL)
{
cout << temp->data << " ";
if (chance == 1)
mycout1 << temp->data << " ";
else
mycout2 << temp->data << " ";
temp = temp->next;
}
cout << endl;
} //删除节点
void List::deleteData(int addNum)
{
int i, j = 0;
cout << "请问您要删除第几个数据: ";
cin >> i;
Node* tp = NULL;
Node* link = head;//link为删除节点后面的一个节点,temp为删除节点 if (addNum < i || i < 0)
cout << "操作非法!!" << endl;
else
{
while (link->next)
{
tp = link->next; //第一个节点
j++;
if (i == j) //找的删除的节点
{
link->next = tp->next;
delete tp;
break;
}
link = link->next;
}
travelList(1);
} } //清空链表
void List::clearList()
{
Node* tp = NULL;
Node* ph = head->next; while (head->next)
{
tp = ph;
ph = ph->next;
delete tp;
head->next = ph;
} travelList(1);
cout << endl;
} //询问是否清空
void List::ifClear()
{
string i; if (!head->next)
{
cout << "链表已清空!!!" << endl;
} else
{
cout << "是否清空链表(是/否):";
cin >> i; if (i == "是")
{
clearList();
cout << "链表清空完成!!!" << endl;
}
else
cout << "链表未清空!!!" << endl;
}
} //冒泡排序
void List::bubbleSortList(List& list)
{
//求list链表长度len
int len=0;
//临时指针phead
Node* phead = list.head->next;
while (phead)
{
len++;
phead = phead->next;
} //冒泡排序
for (int i=0;i<len-1; i++)
{
//phead指向头结点
phead = list.head;
//ph1指向首元结点
Node* ph1 = phead->next;
//ph2指向首元结点的后继
Node* ph2 = ph1->next;
//进入循环冒出最大的数
for (int j = 0; j < len - 1 - i; j++)
{
//如果前面的值大于后面的值则交换
if (ph1->data > ph2->data)
{
phead->next = ph2;
ph1->next = ph2->next;
ph2->next = ph1; //结点交换后,ph1与ph2位置颠倒回来
Node* temp = ph1;
ph1 = ph2;
ph2 = temp;
} //如果不需要交换,三指针移动
phead = phead->next;
ph1 = ph1->next;
ph2 = ph2->next;
}
} //打印结点数据
phead = list.head->next;
while (phead)
{
cout << phead->data << " ";
phead = phead->next;
}
cout << endl;
} //下标重载
int List::operator[](int idx)
{
//临时指针temp,为了防止头指针改变
Node* temp = head;
//如果下标小于链表长度进行取值
if (idx < num)
{
for (int i = 0; i < idx; i++)
{
temp = temp->next;
}
}
return temp->data;
} //+ 重载
List operator +(List & List_1, List & List_2)
{
//由链表1生成链表3
List List_3;
//生成临时指针temp_1
List::Node* temp_1 = List_1.head->next;
//把链表1的值给链表3
while (temp_1)
{
List_3.insertList(temp_1->data);
temp_1 = temp_1->next;
}
//生成临时指针temp_2
List::Node* temp_2 = List_2.head->next;
//把链表2的值给链表3
while (temp_2)
{
List_3.insertList(temp_2->data);
temp_2 = temp_2->next;
} return List_3;
} //- 重载
List operator -(List & List_1, List & List_2)
{
//生成链表4
List List_4;
//生成临时指针temp_1,temp_2
List::Node* temp_1 = List_1.head->next;
List::Node* temp_2 = List_2.head->next;
//flag为1链表2有链表1的值,为0则没有
int flag = 0;
//比较链表一和链表二,不等就将数据存入List_4
while (temp_1)
{
//临时指针temp_2回溯
temp_2 = List_2.head->next;
while (temp_2)
{
//判断是否有相同值
if (temp_1->data == temp_2->data)
{
flag = 1;
break;
}
//指针移动
temp_2 = temp_2->next;
}
//没有相同值List_4则插入数据
if (!flag)
{ List_4.insertList(temp_1->data);
} //指针移动,开始下一轮对比
temp_1 = temp_1->next;
flag = 0;
}
return List_4;
} //重载<<
ostream& operator<<(ostream & os, List & list)
{
list.bubbleSortList(list);
return os;
}
//重载>>
istream &operator>>(istream & is, List & list)
{
int size, i=0;
cout << "(输入链表长度):";
is >> size;
//当i<size时录入数据
while (i < size)
{
int data;
is >> data;
//插入数据
list.insertList(data);
i++;
}
return is;
}
int main()
{
//初始化,生成List_1
List List_1;
//输入链表长度
List_1.input();
//遍历链表,并存入text1文件
List_1.travelList(1);
//添加节点并返回总结点数
int addNum = List_1.addNode();
//删除节点
List_1.deleteData(addNum); //初始化,生成List_2
List List_2;
//输入链表长度
List_2.input();
//遍历链表,并存入text2文件
List_2.travelList(2); //重载下标
cout << "取链表2的第二个元素:";
cout << List_2[2]<<endl;
//重载+
List List_3;
List_3 = List_1 + List_2;
cout << "两链表+为:";
List_3.bubbleSortList(List_3);
//重载-
List List_4;
List_4 = List_1 - List_2;
cout << "两链表-为:";
List_4.bubbleSortList(List_4);
//重载<<
cout << "cout<<List_4:";
cout << List_4 << endl;
//重载>>
List List_5;
cout << "cin>>List_5";
cin >> List_5;
cout << "链表List_5: " << List_5; //询问是否清空链表1
List_1.ifClear(); //关闭打开的文件
mycout1.close();
mycout2.close();
return 0; }

  

用类创建单链表时,可以将结构体封装为私有成员,在构造函数中初始化链表极为方便;链表的删除操作需要先进行遍历,并且遍历途中不能随意改变头结点的位置,所以在进行链表的操作时,皆需要临时变量防止头指针改变;除此之外,在进行冒泡排序时,需要画图理清逻辑,虽然比较过后,链表的连接方式改变了,但是ph1与ph2位置颠倒,需要互换回来,使下一次比较正常运行;运算符“+”号重载时,如果直接由链表1生成链表3,在进行减操作时,会发现链表1随链表3的改变而改变了,导致在进行“-”操作时出错,后在“+”操作时,对链表3进行逐一赋值,问题得到解决。总的来说,此次试验对友元函数和运算符重载有了新的收获,例如如果将”<<”重载,”<<”会根据你输出的内容来调用相应的函数,从而在使用cout时更为方便。

c++单链表冒泡排序(交换结点),链表增删改查,运算符重载的更多相关文章

  1. java实现单链表增删改查

    package 数据结构算法.链表; /* *定义节点 * 链表由节点构成 */ public class Node<E> { private E e; //数据data private ...

  2. 关于单链表的增删改查方法的递归实现(JAVA语言实现)

    因为在学习数据结构,准备把java的集合框架底层源码,好好的过一遍,所以先按照自己的想法把单链表的类给写出来了; 写该类的目的: 1.练习递归 2.为深入理解java集合框架底层源码打好基础 学习的视 ...

  3. Java描述数据结构之链表的增删改查

    链表是一种常见的基础数据结构,它是一种线性表,但在内存中它并不是顺序存储的,它是以链式进行存储的,每一个节点里存放的是下一个节点的"指针".在Java中的数据分为引用数据类型和基础 ...

  4. 05_Elasticsearch 单模式下API的增删改查操作

    05_Elasticsearch 单模式下API的增删改查操作 安装marvel 插件: zjtest7-redis:/usr/local/elasticsearch-2.3.4# bin/plugi ...

  5. Elasticsearch 单模式下API的增删改查操作

    <pre name="code" class="html">Elasticsearch 单模式下API的增删改查操作 http://192.168. ...

  6. $Django orm增删改字段、建表 ,单表增删改查,Django请求生命周期

    1 orm介绍  ORM是什么   ORM 是 python编程语言后端web框架 Django的核心思想,“Object Relational Mapping”,即对象-关系映射,简称ORM.  一 ...

  7. python全栈开发day61-django简单的出版社网站展示,添加,删除,编辑(单表的增删改查)

    day61 django内容回顾: 1. 下载: pip install django==1.11.14 pip install -i 源 django==1.11.14 pycharm 2. 创建项 ...

  8. Django项目的创建与介绍.应用的创建与介绍.启动项目.pycharm创建启动项目.生命周期.三件套.静态文件.请求及数据.配置Mysql完成数据迁移.单表ORM记录的增删改查

    一.Django项目的创建与介绍 ''' 安装Django #在cmd中输入pip3 #出现这个错误Fatal error in launcher: Unable to create process ...

  9. mysql数据库单表增删改查命令

    数据库DB-database-mysql 课程安排 第一天: 1.数据库定义以及设计 2.mysql服务端的安装 3.mysql-dos操作 库的操作 表的操作 4.mysql客户端navicate工 ...

  10. hibernate对单表的增删改查

    ORM: 对象关系映射(英语:Object Relational Mapping,简称ORM,或O/RM,或O/R mapping) 实现对单表的增删改查 向区域表中增加数据: 第一步: 新建一个Da ...

随机推荐

  1. every、some数组方法

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. Windows10 下安装 Apache2.4+PHP7.1+MySQL5.7

    这个教程主要是分享如何快速组建WAMP开发环境,对于软件的详细配置,自行参考文档或搜索. Visual C++ Redistributable for Visual Studio 2015 下载地址: ...

  3. js中的forEach/map方法

    // forEach方法 var data = [{ name: "程咬金", sex: "1", age: 26 }, { name: "程才&qu ...

  4. Element.scrollIntoView()

    Element.scrollIntoView() 方法让当前的元素滚动到浏览器窗口的可视区域内 语法 element.scrollIntoView(); element.scrollIntoView( ...

  5. jQuery和Vue的区别

    1.jQuery和Vue的区别 jQuery是使用选择器($)选取DOM对象,对其进行赋值.取值.事件绑定等操作,其实和原生的HTML的区别只在于可以更方便的选取和操作DOM对象,而数据和界面是在一起 ...

  6. 360开启wifi无网络访问处理办法

    一.背景说明 台式机默认没有无线网卡的,想开个wifi,在电脑上插上了个usb无线网卡然后开启“360免费WiFi”.但显示“无网络访问”,连上之后确实也不能访问外部网站. 二.处理办法 依次打开“控 ...

  7. 微信小程序电商实战(-)商城首页

    首先在app.json中配置页面和底部tabbar { "pages":[ "pages/index/index", "pages/kind/kind ...

  8. ES6笔记(二)

    一.字符串的扩展1. 用于从码点返回到对应字符. String.fromCodePoint(xx)2. for...of可以遍历字符串3. includes():返回布尔值,表示是否找到了参数字符串. ...

  9. linux IPtable防火墙 禁止和开放端口

    1.关闭所有的 INPUT FORWARD OUTPUT 只对某些端口开放.下面是命令实现: iptables -P INPUT DROPiptables -P FORWARD DROPiptable ...

  10. RockerMQ实战之快速入门

    文章目录 RocketMQ 是什么 专业术语 Producer Producer Group Consumer Consumer Group Topic Message Tag Broker Name ...