[数据结构 - 第3章] 线性表之单链表(C++实现)
一、类定义
单链表类的定义如下:
#ifndef SIGNALLIST_H
#define SIGNALLIST_H
typedef int  ElemType; /* "ElemType类型根据实际情况而定, 这里假设为int */
/* 线性表的单链表存储结构 */
typedef struct node
{
	ElemType data; // 数据域
	struct node *next; // 指针域
}Node, LinkList;
class SignalList
{
public:
	SignalList(int size = 0); // 构造函数
	~SignalList(); // 析构函数
	void clearList(); // 清空顺序表操作
	bool isEmpty(); // 判断是否为空操作
	int getLength(); // 获取顺序表长度操作
	bool insertList(int i, const ElemType e); // 插入元素操作
	bool deleteList(int i, ElemType *e); // 删除元素操作
	bool getElem(int i, ElemType *e); // 获取元素操作
	bool insertListHead(const ElemType e); // 头部后插入元素操作
	bool insertListTail(const ElemType e); // 尾部后插入元素操作
	void traverseList(); // 遍历顺序表
	int locateElem(const ElemType e); // 查找元素位置操作
private:
	LinkList *m_pList; // 单链表指针
};
#endif
二、构造函数
为头结点m_pList申请内存,数据域置为 0,指针域指向空。
// 构造函数
SignalList::SignalList(int size)
{
	// 初始化单链表
	m_pList = new Node;
	m_pList->data = 0;
	m_pList->next = NULL;
}
三、析构函数
调用清空单链表方法,并且销毁头结点。
// 析构函数
SignalList::~SignalList()
{
	clearList(); // 清空单链表
	delete m_pList;
	m_pList = NULL;
}
四、清空链表操作
循环销毁除头结点外的各结点。
// 清空链表操作
void SignalList::clearList()
{
	Node *cur; // 当前结点
	Node *temp; // 事先保存下一结点,防止释放当前结点后导致“掉链”
	cur = m_pList->next; //指向第一个结点
	while (cur)
	{
		temp = cur->next; // 事先保存下一结点,防止释放当前结点后导致“掉链”
		delete cur; // 释放当前结点
		cur = temp; // 将下一结点赋给当前结点
	}
	cur->next = NULL; // 注意还要将头结点的指针域指向空
}
清空链表和析构函数的区别:清空链表是循环销毁除头结点外的各结点,析构函数是销毁所有结点,包括头结点。
五、判空和获取顺序表长度操作
// 判断是否为空操作
bool SignalList::isEmpty()
{
	return m_pList->next == NULL ? true : false;
}
// 获取链表长度操作
int SignalList::getLength()
{
	Node *cur = m_pList;
	int length = 0;
	while (cur->next)
	{
		cur = cur->next;
		length++;
	}
	return length;
}
六、插入元素操作
注意这里是有头结点,头结点作为位置 0,所以只能在位置 1 以及后面插入,所以 i 至少为1。
// 插入元素操作
bool SignalList::insertList(int i, const ElemType e)
{
	// 判断链表是否存在
	if (!m_pList)
	{
		cout << "list not exist!" << endl;
		return false;
	}
	// 只能在位置1以及后面插入,所以i至少为1
	if (i < 1)
	{
		cout << "i is invalid!" << endl;
		return false;
	}
	// 找到i位置所在的前一个结点
	Node *front = m_pList; // 这里是让front与i不同步,始终指向j对应的前一个结点
	for (int j = 1; j < i; j++) // j为计数器,赋值为1,对应front指向的下一个结点,即插入位置结点
	{
		front = front->next;
		if (front == NULL)
		{
			printf("dont find front!\n");
			return false;
		}
	}
	// 创建一个空节点,存放要插入的新元素
	Node *temp = new Node;
	temp->data = e;
	temp->next = NULL;
	// 插入结点s
	temp->next = front->next;
	front->next = temp;
	return true;
}
七、删除元素操作
注意提前保存要删除的结点,避免删除结点后丢失。
// 删除元素操作
bool SignalList::deleteList(int i, ElemType *e)
{
	// 判断链表是否存在
	if (!m_pList)
	{
		cout << "list not exist!" << endl;
		return false;
	}
	// 只能删除位置1以及后面的结点
	if (i < 1)
	{
		cout << "i is invalid!" << endl;
		return false;
	}
	// 找到i位置所在的前一个结点
	Node *front = m_pList; // 这里是让front与i不同步,始终指向j对应的前一个结点
	for (int j = 1; j < i; j++) // j为计数器,赋值为1,对应front指向的下一个结点,即插入位置结点
	{
		front = front->next;
		if (front->next == NULL)
		{
			printf("dont find front!\n");
			return false;
		}
	}
	// 提前保存要删除的结点
	Node *temp = front->next;
	*e = temp->data; // 将要删除结点的数据赋给e
	// 删除结点
	front->next = front->next->next;	
	// 销毁结点
	delete temp;
	temp = NULL;
	return true;
}
八、遍历操作
遍历前需要判断链表是否存在。
// 遍历链表
void SignalList::traverseList()
{
	// 判断链表是否存在
	if (!m_pList)
	{
		cout << "list not exist!" << endl;
		return;
	}
	Node *cur = m_pList->next;
	while (cur)
	{
		cout << cur->data << " ";
		cur = cur->next;
	}
}
九、主函数执行
在主函数中执行的代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include "signalList.h"
using namespace std;
int main()
{
	// 初始化链表
	SignalList signleList(20);
	cout << "插入元素0-2到链表!" << endl;
	for (int i = 0; i<3; i++)
	{
		signleList.insertList(i+1, i);
	}
	cout << endl;
	// 在位置2插入元素9到链表
	cout << "在位置2插入元素9到链表!" << endl << endl;
	signleList.insertList(2, 9);
	// 在位置3删除元素
	int value1;
	if (signleList.deleteList(3, &value1) == false)
	{
		cout << "delete error!" << endl;
		return -1;
	}
	else
	{
		cout << "在位置3删除元素,删除的元素为:" << value1 << endl << endl;
	}
	// 查找元素位置
	int index = signleList.locateElem(9);
	if (index == -1)
	{
		cout << "locate error!" << endl;
		return -1;
	}
	else
	{
		cout << "查找到元素9的位置为:" << index << endl << endl;
	}
	// 遍历链表
	cout << "遍历链表: ";
	signleList.traverseList();
	cout << endl << endl;
	// 清空链表
	cout << "清空链表!" << endl << endl;
	signleList.clearList();
	return 0;
}
输出结果如下图所示(编译器为VS2013):

[数据结构 - 第3章] 线性表之单链表(C++实现)的更多相关文章
- 线性表之单链表C++实现
		线性表之单链表 一.头文件:LinkedList.h //单链表是用一组任意的存储单元存放线性表的元素,这组单元可以是连续的也可以是不连续的,甚至可以是零散分布在内存中的任意位置. //单链表头文件 ... 
- 【Java】 大话数据结构(2) 线性表之单链表
		本文根据<大话数据结构>一书,实现了Java版的单链表. 每个结点中只包含一个指针域的链表,称为单链表. 单链表的结构如图所示: 单链表与顺序存储结构的对比: 实现程序: package ... 
- [数据结构 - 第3章] 线性表之双向链表(C语言实现)
		一.什么是双向链表? 双向链表(double linked list)是在单链表的每个结点中,再设置一个指向其前驱结点的指针域.所以在双向链表中的结点都有两个指针域,一个指向直接后继,另一个指向直接前 ... 
- Java数据结构-线性表之单链表LinkedList
		线性表的链式存储结构,也称之为链式表,链表:链表的存储单元能够连续也能够不连续. 链表中的节点包括数据域和指针域.数据域为存储数据元素信息的域,指针域为存储直接后继位置(一般称为指针)的域. 注意一个 ... 
- [C++]数据结构:线性表之(单)链表
		一 (单)链表 ADT + Status InitList(LinkList &L) 初始化(单)链表 + void printList(LinkList L) 遍历(单)链表 + int L ... 
- 数据结构(java版)学习笔记(三)——线性表之单链表
		单链表的优点: 长度不固定,可以任意增删. 单链表的缺点: 存储密度小,因为每个数据元素,都需要额外存储一个指向下一元素的指针(双链表则需要两个指针). 要访问特定元素,只能从链表头开始,遍历到该元素 ... 
- 续上文----线性表之单链表(C实现)
		本文绪上文线性表之顺序表(C实现) 本文将继续使用单链表实现线性表的另外一种存储结构.这种使用链表实现的存储结构在内存中是不连续的. C实现代码如下: #include<stdio.h> ... 
- 线性表 (单链表、循环链表-python实现)
		一.线性表 线性表的定义: 线性表是具有相同数据类型的有限数据的序列. 线性表的特点: 出了第一个元素外,每个元素有且仅有一个直接前驱,除最后一个元素外有且只有一个后继. 线性表是一种逻辑结构,表示元 ... 
- [数据结构 - 第3章] 线性表之顺序表(C++实现)
		一.类定义 顺序表类的定义如下: #ifndef SEQLIST_H #define SEQLIST_H typedef int ElemType; /* "ElemType类型根据实际情况 ... 
随机推荐
- CMDS目的端数据库碎片整理记录
			CMDS目的端数据库碎片整理记录 看看数据库里面需要做整理的表有哪些,条件可以根据需求稍微改动一下 SQL> select * from ( 2 select a.owner, 3 a.tabl ... 
- Tomcat热部署和热加载
			1.热部署与热加载 在应用运行的时候升级软件,无需重新启动的方式有两种,热部署和热加载.它们之间的区别是: (1).部署方式: 热部署在服务器运行时重新部署项目.热加载在运行时重新加载class. ( ... 
- Is Safari on iOS 6 caching $.ajax results? post Cache
			https://stackoverflow.com/questions/12506897/is-safari-on-ios-6-caching-ajax-results Since the upgra ... 
- 最小球覆盖——模拟退火&&三分套三分套三分
			题目 给出 $N(1 \leq N \leq 100)$ 个点的坐标 $x_i,y_i,z_i$($-100000 \leq x_i,y_i,z_i \leq 100000$),求包围全部点的最小的球 ... 
- ant-design-vue有v-decorator时defaultValue无效
			<a-input v-decorator="[ 'userName', { rules: [ { required: true, message: '请输入您的账号!' } ], in ... 
- JS的ES6的class
			1.类的创建: 定义类 类的构造函数 类的静态方法 类的一般属性和方法 //定义类 class Person{ // 类的静态方法,相当于Person.test = function(){consol ... 
- Reactive Extensions (Rx) 入门(1) —— Reactive Extensions 概要
			译文:https://blog.csdn.net/fangxing80/article/details/7381619 原文:http://www.atmarkit.co.jp/fdotnet/int ... 
- 51 Nod 1135 原根
			基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 设m是正整数,a是整数,若a模m的阶等于φ(m),则称a为模m的一个原根.(其中φ(m)表示m的欧拉函数) 给出1个质数P ... 
- luogu P1725 琪露诺
			二次联通门 : luogu P1725 琪露诺 /* luogu P1725 琪露诺 DP + 线段树 用线段树维护dp[i - R] ~ dp[i - L]的最大值 然后 转移方程是 dp[i] = ... 
- Note_3.31
			2019/4/1 奇奇怪怪的笔记 整理了一些之前没有写过的东西,把它们拼在一起,并没有什么逻辑可言qwq FWT快速沃尔什变换 \[ FWT(A)=merge(FWT(A0),FWT(A0+A1)) ... 
