1.初始设置定义
typedef int ElemType; // ElemType代表元素数据类型,可自定义类型
2.单链表结点设置定义
typedef struct LNode{ // 单链表的结点定义
ElemType data; // 链表的数据域
struct LNode *next; // 链表的指针域,指向后继结点
}LNode, *LinkList;
3.初始化创建带头结点的空链表
bool InitList_L(LinkList &L){ // 构造一个空的单链表L
L = new LNode; // 生成新的头结点,用头指针L指向头结点
if(!L)return false; // 生成结点失败
L->next = NULL; // 头结点的指针置空
return true;
}
4.利用头插法创建单链表
void CreateList_H(LinkList &L){ // 利用头插法创建单链表
int n; // 输入n个元素的值,连接在带头结点的单链表上
LinkList s;
L = new LNode; // 建立一个带头结点L的空链表
L->next = NULL; // 当前头结点L的后继为空
printf("请输入元素个数n:");
scanf("%d",&n);
printf("请依次输入n个元素:\n");
while(n--){
s = new LNode; // 生成新的结点s
scanf("%d",&s->data); // 将输入数据赋给新结点s的数据域
s->next = L->next; // 将新结点s插入头结点L之后
L->next = s; // 令头结点指向当前新插入的结点
}
}
5.利用尾插法创建单链表
void CreateList_R(LinkList &L){ // 利用尾插法创建单链表
int n; // 输入n个元素的值,连接在带头结点的单链表上
LinkList s,r;
L = new LNode; // 建立一个带头结点L的空链表
L->next = NULL; // 当前头结点L的后继为空
r = L; // 当前单链表仅有头结点L,所以头结点L也即当前尾结点r
printf("请输入元素个数n:");
scanf("%d",&n);
printf("请依次输入n个元素:\n");
while(n--){
s = new LNode; // 生成新的结点s
scanf("%d",&s->data); // 将输入数据赋给新结点s的数据域
s->next = NULL; // 新结点s将作为新的尾结点所以其后继为空
r->next = s; // 令r指向新结点s使新结点s插入原尾结点r之后
r = s; // 当前尾结点为s,则更新r为最新尾结点
}
}
6.在单链表中查找第i个元素的值
bool GetElem_L(LinkList L, int i, int &e){ // 在带头结点的单链表L中查找第i个元素
// 用e记录L中第i个元素的值
int j = 1; // j为计数器
LinkList p;
p = L->next; // p指向第一个数据结点,以此为起点
while(j<i && p){ // 顺着链表向后扫描,直至p指向第i个元素或p为空
p = p->next; // 指向下一个结点
j++; // 计数+1
}
if(!p || j>i)return false; // 当i值超限则查找失败
e = p->data; // 取第i个结点的数据域
return true;
}
7.在单链表中查找元素e是否存在
bool LocateElem_L(LinkList L, int e){ // 在带头结点的单链表中查找元素e是否存在
LinkList p;
p = L->next; // p指向第一个数据结点,以此为起点
while(p && p->data!=e) // 顺着链表向后扫描,直至p指向元素e或p为空
p = p->next;
if(!p)return false; // 当p值为空则查找失败
return true;
}
8.在单链表的第i个位置插入元素e
bool ListInsert_L(LinkList &L, int i, int e){ // 在带头结点的单链表中第i个位置插入元素e
int j = 0;
LinkList p,s;
p = L; // p指向头结点,以此为起点
while(p && j<i-1){ // 顺着链表向后扫描,直至p指向第i-1个位置或p为空
p = p->next;
j++;
}
if(!p || j>i-1)return false; // 当i超限时插入失败
s = new LNode; // 生成新结点s
s->data = e; // 将e放入新结点s的数据域
s->next = p->next; // 将新结点的指针域指向第i个结点
p->next = s; // 将结点p的指针域指向结点s
return true;
}
9.在单链表中删除第i个位置元素
bool ListDelete_L(LinkList &L, int i){ // 在带头结点的单链表中删除第i个位置元素
LinkList p,q;
int j = 0;
p = L; // p指向头结点,以此为起点
while((p->next) && (j<i-1)){ // 查找被删除结点的前驱结点
p = p->next;
j++;
}
if(!(p->next) || (j>i-1))return false; // 当被删除结点为空或i超限时查找失败
q = p->next; // 临时保存被删除结点的地址,使q作为当前被删除结点
p->next = q->next; // 将q结点的后继地址赋给p结点的指针域
delete q; // 释放q的内存空间以实现删除
return true;
}
10.合并有序单链表La和Lb
void MergeLinkList(LinkList La, LinkList Lb, LinkList &Lc){ // 合并有序单链表La和Lb生成Lc
LinkList p,q,r;
p = La->next; // p指向La的第一个元素结点
q = Lb->next; // q指向Lb的第一个元素结点
Lc = La; // Lc指向La的头结点
r = Lc; // r指向新链表Lc的尾结点
while(p && q){
if(p->data <= q->data){ // 串起p指向的结点
r->next = p;
r = p;
p = p->next;
}else{ // 串起q指向的结点
r->next = q;
r = q;
q = q->next;
}
}
r->next = p ? p : q; // 相当于if(p)r->next = p;else r->next = q;
delete Lb;
}
11.将单链表元素顺序倒置
void ReverseLinkList(LinkList &L){ // 将单链表元素顺序倒置
LinkList p,q;
p = L->next; // p指向L的第一个元素
L->next = NULL; // 头结点后继置空
while(p){
q = p->next; // q指向p的下一结点,记录断点
p->next = L->next; // 头插法
L->next = p;
p = q; // 指针后移
}
}
12.查找链表中间结点(单双链表均适用)
LinkList FindMiddle(LinkList L){ // 查找链表中间位置结点
LinkList p,q;
p = L; // p为快指针
q = L; // q为慢指针
while(p && p->next){
p = p->next->next; // 快指针p一次经过两个结点
q = q->next; // 慢指针q一次经过一个结点
}
return q; // 此时q的位置即为单链表中间结点位置
}
13.查找链表倒数第k位结点(单双链表均适用)
LinkList FindK(LinkList L, int k){ // 查找链表倒数第k位结点
LinkList p,q;
p = L->next; // p为快指针
q = L->next; // q为慢指针
while(p->next){
if(--k <= 0)q = q->next; // k减至0时,慢指针q开始走
p = p->next; // 快指针p先走k-1步
}
if(k>0)return NULL; // 若倒数第k位不存在则返回空
else return q; // 若存在倒数第k位则将其结点返回
}
14.单链表元素去重
void DeleteRep(LinkList &L){ // 单链表去重
LinkList p,q;
int x;
bool flag[n+1] = {}; // 标记出现过的元素,n为单链表中元素最大值
p = L; // 指向头结点
while(p->next){
x = abs(p->next->data);
if(flag[x]){ // 若该元素出现过
q = p->next; // q指向p的下一结点
p->next = q->next; // 删除重复元素结点
delete q; // 释放重复元素结点空间
}else{ // 若该元素未出现过
flag[x] = 1; // 在标记数组的元素位做标记
p = p->next; // 指针后移
}
}
}