目录
前言
这篇博客主要介绍单链表的表示和实现。
一、顺序表的优缺点
线性表的顺序存储结构的特点是逻辑关系上相邻的两个元素在物理位置上也相邻,因此可以随机存取表中任一元素,它的存储位置可用一个简单直观的公式来表示。当然这种存储结构也存在弱点:在作插入或删除操作时,需移动大量元素。
二、单链表的表示和实现
单链表的两个要素:数据域,指针域。其中数据域表示的是当前结点的数据,指针域指向的下一个结点的地址。
单链表的定义如下:
cpp
// - - - - - 线性表的单链表存储结构 - - - - -
typedef int ElemType;
typedef int Staus;
typedef struct LNode {
ElemType data; // 数据域
struct LNode *next; // 指针域
} LNode, *LinkList;
1.初始化
cpp
// 链表初始化
Staus initLinkList(LinkList &linkList) {
linkList = new LNode; // 创建头结点
if (!linkList) { // 内存分配失败
return false;
}
linkList->next = nullptr; // 头结点的指针域置空
return true;
}
2.清空表
遍历单链表,置空指针
cpp
// 清空链表
void clearLinkList(LinkList &linkList) {
LinkList p, q;
p = linkList->next;
while (p) {
q = p;
p = p->next;
delete q;
}
linkList->next = nullptr;
}
3.销毁
cpp
// 销毁链表
void destroyLinkList(LinkList &linkList) {
clearLinkList(linkList);
delete linkList;
linkList = nullptr;
}
4.表长
cpp
// 表长
int linkListLength(LinkList &link){
LNode * p = link->next;
int len = 0;
while (p) {
p = p->next;
len++;
}
return len;
}
5.表空
cpp
// 表空
Status linkListEmpty(LinkList &link){
return linkListLength(link) == 0;
}
6.获取表中的元素
cpp
// 获取表中的元素
Status getElemLinkList(LinkList &link,int pos,ElemType * element){
if (pos < 1|| pos > linkListLength(link)) {
return 0;
}
LinkList p = link->next;
int j = 1;
while (p && j < pos) {
p = p ->next;
++j;
}
if (!p ||j > pos) {
return 0;
}
*element = p->data;
return 1;
}
7.下标
cpp
// 获取数据元素element下标
Status getLocateinkList(LinkList &link,ElemType element,int * location){
LinkList p = link->next;
int j = 1;
while (p) {
if (p->data == element) {
* location = j;
return 1;
}
p = p ->next;
++j;
}
return 0;
}
8.直接前驱
cpp
// 直接前驱
Status priorElemLinkList(LinkList &link,ElemType current,ElemType * priorElement){
LinkList p = link->next;
LinkList head = link;
int j = 1;
while (p) {
if (p->data == current) {//找到数据元素
if (j > 1) {
* priorElement = head->data;
return 1;
}
}
p = p ->next;
head = head->next;
++j;
}
return 0;
}
9.直接后继
cpp
// 直接后继
Status nextElemLinkList(LinkList &link,ElemType current,ElemType * nextElement){
LinkList p = link->next;
while (p) {
if (p->data == current) {//找到数据元素
if (p -> next != nullptr) {
* nextElement = p->next->data;
return 1;
}
}
}
return 0;
}
10.插入
cpp
// 单链表插入
Status insertLinkList(LinkList &head, int pos, int element) {
if (pos < 1) { // 位置非法
return 0;
}
LinkList p = head;
int j = 0;
while (p && j < pos - 1) {
p = p->next;
++j;
}
if (!p || j > pos - 1) {
return 0;
}
LinkList q = new LNode; // 生成新节点
if (!q) { // 内存分配失败
return 0;
}
q->data = element;
q->next = p->next;
p->next = q;
return 1;
}
11.删除
cpp
// 单链表删除
Status deleteLinkList(LinkList &head, int pos) {
if (pos < 1 || !head->next) { // 位置非法或空链表
return false;
}
LinkList p = head;
int j = 0;
while (p->next && j < pos - 1) { // 找到要删除结点的前一个结点
p = p->next;
++j;
}
if (!p->next || j > pos - 1) { // 删除位置超出范围
return false;
}
LinkList q = p->next; // 要删除的结点
p->next = q->next; // 前一个结点指向后一个结点
delete q; // 释放删除结点的内存
return true;
}
12.遍历链表
cpp
// 遍历链表
void traverseList(LinkList linkList) {
LinkList p = linkList->next;
while (p) {
cout << p->data << " ";
p = p->next;
}
cout << endl;
}
13.测试代码
cpp
void testLinkList(void){
LinkList myList;
if (!initLinkList(myList)) {
cout << "链表初始化失败!" << endl;
}
cout<<"表长:"<<linkListLength(myList)<<endl;
int values[] = {1, 2, 3, 4, 5};
int size = sizeof(values) / sizeof(values[0]);
if (!createLinkList(myList, values, size)) {
cout << "创建链表失败!" << endl;
destroyLinkList(myList); // 避免内存泄漏
}
cout << "链表元素:";
traverseList(myList);
cout<<"表长:"<<linkListLength(myList)<<endl;
cout << "获取某个位置的数据元素"<<endl;
for (int i = -1; i <= 6; i++) {
int element;
if (getElemLinkList(myList, i, &element)) {
cout<<"第"<<i<<"个数据元素获取成功,数据元素为:"<<element<<"\t"<<endl;
}else{
cout<<"第"<<i<<"个数据元素获取失败!"<<endl;
}
}
cout<<endl;
cout << "获取单链表数据元素下标"<<endl;
for (int i = -1; i <= 6; i++) {
int locate;
if (getLocateinkList(myList, i, &locate)) {
cout<<"数据元素"<<i<<"下标获取成功,下标为:"<<locate<<"\t"<<endl;
}else{
cout<<"数据元素"<<i<<"下标获取失败!"<<endl;
}
}
cout<<endl;
cout << "获取单链表数据元素直接前驱"<<endl;
for (int i = -1; i <= 6; i++) {
int element;
if (priorElemLinkList(myList, i, &element)) {
cout<<"数据元素"<<i<<"直接前驱为:"<<element<<"\t"<<endl;
}else{
cout<<"数据元素"<<i<<"没有直接前驱!"<<endl;
}
}
// 插入元素
int insertPos = 3;
int insertElement = 10;
if (!insertLinkList(myList, insertPos, insertElement)) {
cout << "插入元素失败!" << endl;
destroyLinkList(myList); // 避免内存泄漏
}
cout << "插入后的链表元素:";
traverseList(myList);
// 删除元素
int deletePos = 2;
if (!deleteLinkList(myList, deletePos)) {
cout << "删除元素失败!" << endl;
destroyLinkList(myList); // 避免内存泄漏
}
cout << "删除后的链表元素:";
traverseList(myList);
// 清空链表
clearLinkList(myList);
cout << "链表已清空!" << endl;
// 销毁链表
destroyLinkList(myList);
cout << "链表已销毁!" << endl;
}