首先是单链表的定义,使用结构体定义两个部分,分别是数据域和指针域。
点击查看代码
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode, *LinkList;
这里可以使用typedef关键字将后续的定义简化。
具体例子如下:
- 如果这样定义struct LNode{}的话。在定义LNode类型变量的时候我们需要这样写,struct LNode L;
- 如果是使用typedef可以将struct省略掉。直接这样写:LNode L;
对链表的初始化(带头节点、不带头节点)
点击查看代码
// 无头节点初始化链表
bool InitListNoHead(LinkList &L){
return (L == NULL);
}
// 有头节点的初始化链表
bool InitListWithHead(LinkList &L){
L = (LNode *) malloc(sizeof(LNode));
if(L == NULL) return 0;
L->next = NULL;
return 1;
}
单链表的插入(指定位置插入、节点前后插入)
点击查看代码
// 在链表中指定位置插入值
bool InsertElemPos(LinkList &L, int pos, int e){
if(pos < 1) return 0;
LNode *p = L;
int j = 0;
while(p != NULL && j < pos - 1){
p = p->next;
j ++;
}
if(p == NULL) return 0;
LNode *t = (LNode*)malloc(sizeof(LNode));
t->data = e;
t->next = p->next;
p->next = t;
return 1;
}
// 链表中指定节点后面插入(后插)
bool InsertNextNode(LNode *p, ElemType e){
if(p == NULL) return 0;
LNode *s = (LNode *)malloc(sizeof(LNode));
if(s == NULL) return 0;
s->data = e;
s->next = p->next;
p->next = s;
return 1;
}
// 链表中指定节点前面插入(前插)
// 注意前插操作要确定是不是第一个节点,是的话要特殊处理
bool InsertPriorNode(LNode *p, ElemType e){
// cout << (p->data) << endl;
// p = p->next;
if(p == NULL) return 0;
LNode *s = (LNode*)malloc(sizeof(LNode));
if(s == NULL) return 0;
s->next = p->next;
s->data = p->data;
p->data = e;
p->next = s;
return 1;
}
链表的删除操作
点击查看代码
// 删除第pos个节点并传回
bool DeleteNodePos(LinkList L, int pos, ElemType &e){
if(pos < 1) return 0;
LNode *p = L;
int j = 0;
while(p != NULL && j < pos - 1){
p = p->next;
j ++;
}
if(p == NULL || p->next == NULL) return 0;
e = p->next->data;
p->next = p->next->next;
return 1;
}
// 删除指定节点
// 如果要删除的是最后一个会出现无值可删的bug
bool DeleteNodeVal(LNode *p){
if(p == NULL) return 0;
p->data = p->next->data;
p->next = p->next->next;
return 1;
}
获取链表元素以及获取长度
点击查看代码
// 链表中获取第i个节点
LNode *GetElem(LinkList L, int i){
if(i < 0) return NULL;
LNode *p;
int j = 0;
p = L;
while(p != NULL && j < i){
p = p->next;
j ++;
}
return p;
}
// 链表中获取值为e的节点
LNode *LocateElem(LinkList L, ElemType e){
LNode *p = L;
while(p != NULL && p->data != e){
p = p->next;
}
return p;
}
// 获取链表长度
int GetLength(LinkList L){
LNode *p = L;
int len = 0;
while(p->next != NULL){
p = p->next;
len ++;
}
return len;
}
链表头插、尾插实现初始化
点击查看代码
// 尾插节点
LinkList List_TailInsert(LinkList &L, int n){
int x;
L = (LinkList)malloc(sizeof(LNode));
LNode *s, *p = L;
for(int i = 1;i <= n;i ++){
cin >> x;
s = (LNode *)malloc(sizeof(LNode));
s->data = x;
p->next = s;
p = s;
}
p->next = NULL;
return L;
}
// 头插节点 (逆置链表操作)
LinkList List_HeadInsert(LinkList &L, int n){
int x;
L = (LinkList)malloc(sizeof(LNode));
L->next = NULL; // 没这句话就是无头节点的链表
LNode *s, *p = L;
for(int i = 1;i <= n;i ++){
cin >> x;
s = (LNode *)malloc(sizeof(LNode));
s->data = x;
s->next = p->next;
p->next = s;
}
return L;
}
output链表
void ListPrint(LNode *L){
LNode *p = L;
p = p->next;
while(p != NULL){
cout << p->data << ' ';
p = p->next;
cout << endl;
}
完整代码:
点击查看代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
typedef int ElemType;
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode, *LinkList;
// 无头节点初始化链表
bool InitListNoHead(LinkList &L){
return (L == NULL);
}
// 有头节点的初始化链表
bool InitListWithHead(LinkList &L){
L = (LNode *) malloc(sizeof(LNode));
if(L == NULL) return 0;
L->next = NULL;
return 1;
}
// 在链表中指定位置插入值
bool InsertElemPos(LinkList &L, int pos, int e){
if(pos < 1) return 0;
LNode *p = L;
int j = 0;
while(p != NULL && j < pos - 1){
p = p->next;
j ++;
}
if(p == NULL) return 0;
LNode *t = (LNode*)malloc(sizeof(LNode));
t->data = e;
t->next = p->next;
p->next = t;
return 1;
}
// 链表中指定节点后面插入(后插)
bool InsertNextNode(LNode *p, ElemType e){
if(p == NULL) return 0;
LNode *s = (LNode *)malloc(sizeof(LNode));
if(s == NULL) return 0;
s->data = e;
s->next = p->next;
p->next = s;
return 1;
}
// 链表中指定节点前面插入(前插)
bool InsertPriorNode(LNode *p, ElemType e){
// cout << (p->data) << endl;
p = p->next;
if(p == NULL) return 0;
LNode *s = (LNode*)malloc(sizeof(LNode));
if(s == NULL) return 0;
s->next = p->next;
s->data = p->data;
p->data = e;
p->next = s;
return 1;
}
// 删除第pos个节点并传回
bool DeleteNodePos(LinkList L, int pos, ElemType &e){
if(pos < 1) return 0;
LNode *p = L;
int j = 0;
while(p != NULL && j < pos - 1){
p = p->next;
j ++;
}
if(p == NULL || p->next == NULL) return 0;
e = p->next->data;
p->next = p->next->next;
return 1;
}
// 删除指定节点
bool DeleteNodeVal(LNode *p){
if(p == NULL) return 0;
p->data = p->next->data;
p->next = p->next->next;
return 1;
}
// 链表中获取第i个节点
LNode *GetElem(LinkList L, int i){
if(i < 0) return NULL;
LNode *p;
int j = 0;
p = L;
while(p != NULL && j < i){
p = p->next;
j ++;
}
return p;
}
// 链表中获取值为e的节点
LNode *LocateElem(LinkList L, ElemType e){
LNode *p = L;
while(p != NULL && p->data != e){
p = p->next;
}
return p;
}
// 获取链表长度
int GetLength(LinkList L){
LNode *p = L;
int len = 0;
while(p->next != NULL){
p = p->next;
len ++;
}
return len;
}
// 尾插节点
LinkList List_TailInsert(LinkList &L, int n){
int x;
L = (LinkList)malloc(sizeof(LNode));
LNode *s, *p = L;
for(int i = 1;i <= n;i ++){
cin >> x;
s = (LNode *)malloc(sizeof(LNode));
s->data = x;
p->next = s;
p = s;
}
p->next = NULL;
return L;
}
// 头插节点 (逆置链表操作)
LinkList List_HeadInsert(LinkList &L, int n){
int x;
L = (LinkList)malloc(sizeof(LNode));
L->next = NULL; // 没这句话就是无头节点的链表
LNode *s, *p = L;
for(int i = 1;i <= n;i ++){
cin >> x;
s = (LNode *)malloc(sizeof(LNode));
s->data = x;
s->next = p->next;
p->next = s;
}
return L;
}
// 打印链表
void ListPrint(LNode *L){
LNode *p = L;
p = p->next;
while(p != NULL){
cout << p->data << ' ';
p = p->next;
}
cout << endl;
}
int main(){
LinkList L;
ElemType val;
int n; cin >> n;
List_HeadInsert(L, n);
ListPrint(L);
cout << "获取链表长度:\n";
int len = GetLength(L);
cout << "len:" << len << endl;
cout << "插入指定位置:\n";
InsertElemPos(L, 3, 3);
ListPrint(L);
cout << "插入指定节点的后面:\n";
InsertNextNode(L, 3);
ListPrint(L);
cout << "插入指定节点的前面:\n";
InsertPriorNode(L, 100);
ListPrint(L);
cout << "获取第i个节点:\n";
LNode *T = GetElem(L, 2);
cout << (T->data) << endl;
cout << "获取值为e的节点:\n";
T = LocateElem(L, 2);
cout << (T->data) << endl;
cout << "删除第3个节点:\n";
DeleteNodePos(L, 3, val);
cout << val << endl;
ListPrint(L);
return 0;
}