[C++]数据结构:线性表之(单)链表
一 (单)链表 ADT
+ Status InitList(LinkList &L) 初始化(单)链表
+ void printList(LinkList L) 遍历(单)链表
+ int ListLength(LinkList L) 获得表长
+ void CreateList_Head(LinkList &L, int n) 创建单链表 (头插法)【重点】
+ void CreateList_Rear(LinkList &L, int n) 创建单链表 (尾插法) 【重点】
+ Status GetElement(LinkList L, int i, ElementType &e) (按位)取值
+ LNode *LocateElement(LinkList L, ElementType e) (按值)查找
+ Status ListInsert(LinkList &L, int i, ElementType e) (按位)插入 【重点 | 易错】
+ Status ListDelete(LinkList &L, int i) (按位)删除 【重点 | 易错/易混】
二 编程实现
2.1 定义基础数据类型
ElementType (数据元素类型/结构体)
struct ElementType {
char data; // char -> ElementType
bool operator==(const ElementType b) const{ // 重载结构体 ElementType 的运算符
return this->data == b.data;
}
bool operator!=(const ElementType b) const{
return this->data != b.data;
}
};
Status (状态/枚举类型)
enum Status { ERROR, OK, OVERFLOW };
LNode(单链表结点/结构体) / LinkList (单链表/结构体)
typedef struct LNode { // typedef 关键字 可使用它来为类型取一个新的名称 like: typedef unsigned char BYTE;
ElementType data; //数据域
LNode *next; // 指针域
}*LinkList; // *LinkList 本质上等同于 *LNode
2.2 初始化(单)链表
Status InitList(LinkList &L)
Status InitList(LinkList &L){
L = new LNode; // 生成新结点 作为 头结点 , 头指针L指向头结点
L->next = NULL; // next指针 置空(挂起)
return OK;
}
2.3 遍历(单)链表
void printList(LinkList L)
void printList(LinkList L){
LNode *p;
p = L->next;
printf("[LinkList.h#printList] List->elements: ");
while(p != NULL){
printElementType(p->data);
printf("\t");
p = p->next;
}
printf("\n");
}
2.4 获得表长
int ListLength(LinkList L)
int ListLength(LinkList L){
LNode *p = L->next; // 指针p 指向首元结点
int i = 0; //
while(p){ // 当前结点不为空
p = p->next;
i ++; // 长度 +1
}
return i;
}
2.5-1 创建单链表 (头插法)
void CreateList_Head(LinkList &L, int n)
void CreateList_Head(LinkList &L, int n){ // n: 要输入的元素个数
L = new LNode; // 生成头结点
L->next = NULL;
for(int i=0;i<n;i++){
LNode *s = new LNode; // 生成新结点
printf("\ninput -> element: ");
cin>>( s->data.data );
s->next = L->next; //链接 新结点
L->next = s;
}
}
2.5-2 创建单链表 (尾插法)
void CreateList_Rear(LinkList &L, int n)
void CreateList_Rear(LinkList &L, int n){ // n: 要输入的元素个数
L = new LNode;
L->next = NULL;
LNode *rear = L; // 初始化 尾指针 rear 指向 头结点
for(int j=0; j<n; j++){
LNode *s = new LNode; // 生成新结点
printf("\ninput -> element: ");
cin>>s->data.data;
s->next = rear->next; //链接 新结点
rear->next = s;
rear = rear->next; // 尾指针 rear 指向 新生成的尾结点
}
}
2.6 (按位)取值
Status GetElement(LinkList L, int i, ElementType &e)
Status GetElement(LinkList L, int i, ElementType &e){
LNode *p = L->next; // 指针p 指向首元结点
int j = 1;
while(p != NULL && j<i){
p = p->next;
j++;
}
if(j>i || p==NULL){ // i值不合法 i>n 或 i<0
return ERROR;
}
e = p->data; // 赋值
return OK;
}
2.7 (按值)查找
LNode *LocateElement(LinkList L, ElementType e)
LNode *LocateElement(LinkList L, ElementType e){
LNode *p = L->next; // 指针p 指向首元结点
while(p!=NULL && p->data!=e){
p = p->next;
}
return NULL;
}
2.8 (按位)插入
Status ListInsert(LinkList &L, int i, ElementType e)
Status ListInsert(LinkList &L, int i, ElementType e){
LNode *p = L; // 指针p 指向头结点 【易错: 必须是头结点, 如果初始化p指向 首元结点(p = L->next), 那么 当i=1时, 会与 if(j>i-1 || p == NULL)中的"p == NULL"自相矛盾】
int j = 0; // j 表示下标(明确j的意义很重要, 到底是 表示 下标(从0开始) 还是位置序号(从1开始) )
while(j<i-1 && p!= NULL){ // 移动指针p 指向 第 i-1 个元素上 (即 使得 下标 j 最大等于 i-2)
p = p->next;
j++;
}
if(j>i-1 || p == NULL){ // 判断 i 值 是否合法 i>n 或者 i<0
return ERROR;
}
LNode *s = new LNode; // 生成新结点
s->data = e;
s->next = p->next; // 链接 新结点 与 原第 i 个结点
p->next = s;
return OK;
}
2.9 (按位)删除
Status ListDelete(LinkList &L, int i)
Status ListDelete(LinkList &L, int i){
LNode *p = L; //指针p 指向首元结点
int j = 0; // j 表示 下标 (j 用于 下一次的循环判断条件)
LNode *q; // 定位被删除结点
while( (p != NULL) && (j<i-1) ){ // 指针p 移动到 第 i-1 个元素上 (即 j 最大取值为: i-1 )
//【易混】 (p != NULL) 可以换成 (p->next != NULL),无任何影响,原因:设置该判断条件主要目的是 为了 指针p 能够继续往后移动
printf("(old) p->data: %c\n", p->data.data);
p = p->next;
printf("(new) p->data: %c\n--------------\n", p->data.data);
j++;
}
if( j > i-1 || p->next == NULL ){ // 【易错: p != NULL (考虑的因素是: i>n )】
//【易错】 此处的 p->next == NULL 的判断条件不能轻易换成 p == NULL 因为 必须满足 p 指向于 被删除的第 i 个 (非空)结点的前置结点
// 即 要满足 第 i 个结点非空 ,且 p 指向的是其前置结点 所以 只能为 p->next == NULL
printf("j:%d\n", j);
return ERROR;
}
q = p->next;
p->next = q->next;
delete q; // 释放被删除结点的空间
return OK;
}
三 测试运行(Main.cpp)
#include <stdio.h>
//#include <iostream.h>
#include <iostream>
using namespace std; #include "base.h"
#include "LinkList.h" int main(){
LinkList L; // *LinkList 本质上等同于 *LNode InitList(L); // 初始化(单)链表 L int i = ListLength(L);
printf("length: %d \n",i); ElementType e;
Status status; e.data = 'A';
status = ListInsert(L, 1, e);
printf("status (after insert) : %d\n", status);
printList(L); e.data = 'B';
status = ListInsert(L, 2, e);
printf("status (after insert) : %d\n", status);
printList(L); e.data = 'C';
status = ListInsert(L, 3, e);
printf("status (after insert) : %d\n", status);
printList(L); status = ListDelete(L, 0);
printf("status (after delete) : %d\n", status);
printList(L); status = ListDelete(L, 4);
printf("status (after delete) : %d\n", status);
printList(L); status = ListDelete(L, 3);
printf("status (after delete) : %d\n", status);
printList(L); CreateList_Rear(L, 5); // input: A B C D E
printList(L); return 0;
}
运行结果
length: 0
status (after insert) : 1
[LinkList.h#printList] List->elements: A
status (after insert) : 1
[LinkList.h#printList] List->elements: A B
status (after insert) : 1
[LinkList.h#printList] List->elements: A B C
j:0
status (after delete) : 0
[LinkList.h#printList] List->elements: A B C
(old) p->data:
(new) p->data: A
--------------
(old) p->data: A
(new) p->data: B
--------------
(old) p->data: B
(new) p->data: C
--------------
j:3
status (after delete) : 0
[LinkList.h#printList] List->elements: A B C
(old) p->data:
(new) p->data: A
--------------
(old) p->data: A
(new) p->data: B
--------------
status (after delete) : 1
[LinkList.h#printList] List->elements: A B input -> element: A input -> element: B input -> element: C input -> element: D input -> element: E
[LinkList.h#printList] List->elements: A B C D E
四 参考资料
1 《数据结构(C语言版 第二版)》.严蔚敏.李冬梅.吴伟民
[C++]数据结构:线性表之(单)链表的更多相关文章
- Java数据结构-线性表之单链表LinkedList
线性表的链式存储结构,也称之为链式表,链表:链表的存储单元能够连续也能够不连续. 链表中的节点包括数据域和指针域.数据域为存储数据元素信息的域,指针域为存储直接后继位置(一般称为指针)的域. 注意一个 ...
- [数据结构 - 第3章] 线性表之单链表(C++实现)
一.类定义 单链表类的定义如下: #ifndef SIGNALLIST_H #define SIGNALLIST_H typedef int ElemType; /* "ElemType类型 ...
- 线性表之单链表C++实现
线性表之单链表 一.头文件:LinkedList.h //单链表是用一组任意的存储单元存放线性表的元素,这组单元可以是连续的也可以是不连续的,甚至可以是零散分布在内存中的任意位置. //单链表头文件 ...
- [数据结构-线性表1.2] 链表与 LinkedList<T>(.NET 源码学习)
[数据结构-线性表1.2] 链表与 LinkedList<T> [注:本篇文章源码内容较少,分析度较浅,请酌情选择阅读] 关键词:链表(数据结构) C#中的链表(源码) 可空类 ...
- 【Java】 大话数据结构(2) 线性表之单链表
本文根据<大话数据结构>一书,实现了Java版的单链表. 每个结点中只包含一个指针域的链表,称为单链表. 单链表的结构如图所示: 单链表与顺序存储结构的对比: 实现程序: package ...
- 数据结构(java版)学习笔记(三)——线性表之单链表
单链表的优点: 长度不固定,可以任意增删. 单链表的缺点: 存储密度小,因为每个数据元素,都需要额外存储一个指向下一元素的指针(双链表则需要两个指针). 要访问特定元素,只能从链表头开始,遍历到该元素 ...
- 续上文----线性表之单链表(C实现)
本文绪上文线性表之顺序表(C实现) 本文将继续使用单链表实现线性表的另外一种存储结构.这种使用链表实现的存储结构在内存中是不连续的. C实现代码如下: #include<stdio.h> ...
- 线性表 (单链表、循环链表-python实现)
一.线性表 线性表的定义: 线性表是具有相同数据类型的有限数据的序列. 线性表的特点: 出了第一个元素外,每个元素有且仅有一个直接前驱,除最后一个元素外有且只有一个后继. 线性表是一种逻辑结构,表示元 ...
- Java数据结构-线性表之静态链表
静态链表的定义: 节点由一个一维数组和一个指针域组成,数组用来存放数据元素,而指针域里面的指针(又称游标)用来指向下一个节点的数组下标. 这种链表称之为静态链表. 链表中的数组第一个和最后一个位置须要 ...
随机推荐
- C#中设置密码框 ,用符号代替密码
添加控件 添加控件 确认键代码 private void button1_Click(object sender, EventArgs e) { //修改密码.新密码,重复新密码,两次输入的新密码必须 ...
- 火狐新版移除developer Toolbar和无法关闭自动更新的解决
随着火狐的不断更新已经更新到66版本了,近期注意到有个问题是火狐经常提示更新,更新了没多久,又时不时跳出更新的提示,不胜其烦. 在火狐的前期的版本中(大概4年之前吧)在Options菜单里是可以设置从 ...
- Java 基础 - Collection集合通用方法及操作/ArrayList和LinkedList的差别优势 /弃用的Vector
Collection的笔记: /**存储对象考虑使用: * 1.数组, ①一旦创建,其长度不可变!② 长度难于应对实际情况 * 2.Java集合, ①Collection集合: 1.set: 元素无序 ...
- Vue入门到出门
原来微信小程序的js跟这个差不多啊.这个也不像jQuery那种完全是为了方便写js的感觉,难道算前端框架?还不太了解,总之要先看看,然后用HBuilder快点上手做点东西…… ------------ ...
- [转载]es6 Promise.resolve()方法
es6 Promise.resolve()方法 2018-01-27 22:29:06 ixygj197875 阅读数 16925更多 分类专栏: ES6标准入门 (阮一峰) ES6标准入门 Pr ...
- 在浏览器端用H5实现图片压缩上传
一.需求的场景: 在我们的需求中需要有一个在手机浏览器端,用户实现上传证件照片的功能,我们第一版上了一个最简版,直接让用户在本地选择图片,然后上传到公司公共的服务器上. 功能实现后我们发现一个问题,公 ...
- http文件服务器上传与下载功能
https://www.cnblogs.com/liferecord/p/4843615.html
- 启动文件startup_stm32f40_41xxx.s
一.启动文件,startup_stm32f40x_41xx.s 1.定义 启动文件由汇编编写,是系统上电复位后第一执行的程序. Stack_Size EQU 0x00000400 // 栈的大小可以调 ...
- NOIP考前总结
最近出的锅比较多啊,我来总结一下吧 $1.$小心文件名/文件输入输出!别打错了!结束前十分钟一定要检查! $2.$开数组前要算好内存,不要开一个$1e8$或$1e4*1e4$这样的大数组,直接GG $ ...
- 如何更改电脑ip
首先打开控制面板==>点击网络和internet==>点击网络和共享中心==>点击更改适配器设置==>右键无线连接或宽带连接(视情况而定)==>属性==>双击ipv ...