0.定义结点
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode, *LinkList;
//LNode表示节点,LinkList表示头指针
1.初始化
①带头结点
bool InitList(LinkList &L){
L = (LNode *)malloc(sizeof(LNode));//头指针指向头结点
//判断是否分配成功
if(L == NULL)
return false;
//初始化指向空
L ->next = NULL;
return true;
}
②不带头结点
bool InitList(LinkList &L){
L = NULL;//初始化为空表,头指针指向空
return true;
}
2.判空
①带头结点
bool Empty(LinkList L) {
if(L->next == NULL)
return true;
else
return false;
}
②不带头结点
bool Empty(LinkList L) {
if(L == NULL)
return true;
else
return false;
}
3.创建
3.1头插法(常应用于链表逆置)
①带头结点
LinkList List_HeadInsert(LinkList &L) {
InitList(L);//初始化:创建头结点;初始化为空链表
LNode *s;
int x;
scanf("%d", &x);
while(x != 9999) {//输入9999表示结束
s = (LNode*)malloc(sizeof(LNode));
s -> data = x;
s -> next = L -> next;
L -> next = s;
scanf("%d", &x);
}
return L;
}
②不带头结点
LinkList List_HeadInsert(LinkList &L) {
InitList(L);//初始化:初始化为空链表
LNode *s;
int x;
scanf("%d", &x);
while(x != 9999) {//输入9999表示结束
s = (LNode*)malloc(sizeof(LNode));
s -> data = x;
s -> next = L;
L = s;
scanf("%d", &x);
}
return L;
}
每个结点插入的时间复杂度为:O(1)
总时间复杂度:O(n)
3.2尾插法
①带头结点
LinkList List_TailInsert(LinkList &L) {
InitList(L);//初始化:创建头结点;初始化为空链表
LNode *s, *r = L;//r为表尾指针
int x;
scanf("%d", &x);
while(x != 9999) {//输入9999表示结束
s = (LNode*)malloc(sizeof(LNode));
s -> data = x;
r -> next = s;
r = s;
scanf("%d", &x);
}
r -> next = NULL;
return L;
}
②不带头结点
LinkList List_TailInsert(LinkList &L) {
InitList(L);//初始化:初始化为空链表
LNode *s, *r = L;//r为表尾指针
int x;
scanf("%d", &x);
while(x != 9999) {//输入9999表示结束
s = (LNode*)malloc(sizeof(LNode));//创建新结点
s -> data = x;
if (L == NULL) {
L = s;
r = L;
}
else {
r -> next = s;
r = s;
}
scanf("%d", &x);
}
r -> next = NULL;
return L;
}
由于附设了一个尾指针,时间复杂度与头插法相同。
4.查找
4.1按序查找
①带头结点
LNode *GetElem(LinkList L, int i) {
//判断i是否合法
if(i < 0)
return NULL;
int j = 0;
LNode *p = L;//p指向第0个结点
while(p != NULL && j < i){
p = p -> next;
j++;
}
return p;//i>len或查找不成功时返回NULL
}
②不带头结点
LNode *GetElem(LinkList L, int i) {
//判断i是否合法
if(i < 1)
return NULL;
int j = 1;
LNode *p = L;//p指向第1个结点
while(p != NULL && j < i){
p = p -> next;
j++;
}
return p;//i>len或查找不成功时返回NULL
}
4.2按值查找
①带头结点
LNode *LocateElem(LinkList L, ElemType e){
LNode *p = L -> next ;//L指向头结点(第0个结点),p指向第1个结点
while ( p != NULL && p -> data != e )
p = p -> next;
return p ;//查找失败返回NULL
}
②不带头结点
LNode *LocateElem(LinkList L, ElemType e){
LNode *p = L;//p指向第1个结点
while ( p != NULL && p -> data != e )
p = p -> next;
return p ;//查找失败返回NULL
}
查找的时间复杂度都为O(n)
5.插入
5.1 后插(将新结点插入到第i个位置上,即在第i-1个位置后面插入)
bool InsertNextNode(LNode *p, ElemType e){
if(p == NULL)
return false;
LNode *s = (LNode *)malloc(sizeof(LNode));
if(s == NULL)
return false;
s -> data = e;
s -> next = p -> next;
p -> next = s;
return true;
}
①带头结点
bool ListInsert(LinkList &L, int i, ElemType e){
if(i < 1)
return false;
LNode *p = GetElem(L, i-1);
return InsertNextNode(p, e);
}
②不带头结点
bool ListInsert(LinkList &L, int i, ElemType e) {
if(i < 1)
return false;
if(i == 1){//插入第1个结点操作不同
LNode *s = (LNode *)malloc(sizeof(LNode));
s -> data = e;
s -> next = L;
L = s;
return true;
}
LNode *p = GetElem(L, i-1);
return InsertNextNode(p, e);
}
后插的时间复杂度:O(n)
5.2对给定结点p的前插
方案1:转化为上一结点的后插
需要给定头指针,从头开始找到上一结点。
①带头结点
bool InsertPriorNode(LinkList L, LNode *p, ElemType e){
LNode *q = L;
while(q -> next != q)
q = q -> next;
return InsertNextNode(q, e);
}
②不带头结点
bool InsertPriorNode(LinkList L, LNode *p, ElemType e){
LNode *q = L;
if(p == q){
LNode *s = (LNode *)malloc(sizeof(LNode));
s -> data = e;
s -> next = L;
L = s;
return true;
}
while(q -> next != q)
q = q -> next;
return InsertNextNode(q, e);
}
时间复杂度:O(n)
方案2:后插再交换位置
有无头结点相同
bool InsertPriorNode(LNode *p, ElemType e){
if(p == NULL)
return false;
LNode *s = (LNode *)malloc(sizeof(LNode));
if(s == NULL)
return false;
s -> next = p -> next;
p -> next = s;
s -> data = p -> data;
p -> data = e;
return true;
}
时间复杂度:O(1)
6.删除
6.1删除第i个结点
bool DeleteNextNode(LNode *p, ElemType &e){
//i值不合法
if(p == NULL || p -> next == NULL)
return false;
LNode *q = p -> next;
e = q -> data;
p -> next = q -> next;
free(q);
return true;
}
①带头结点
bool ListDelete(LinkList &L, int i, ElemType &e){
if(i < 1)
return false;
LNode *p = GetElem(L, i-1)
return DeleteNextNode(p, e);
}
②不带头结点
bool ListDelete(LinkList &L, int i, ElemType &e){
if(i < 1)
return false;
if(i == 1){
LNode *q = L;
e = q -> data;
L = q -> next;
free(q);
return true;
}
LNode *p = GetElem(L, i-1)
return DeleteNextNode(p, e);
}
6.2删除给定结点p
方案1:找到前驱结点,执行删除操作
需要给定头指针,从头开始找到上一结点。
①带头结点
bool DeleteNode(LNode *p, ElemType &e){
LNode *q = L;
while(q -> next != q)
q = q -> next;
return DeleteNextNode(q, e);
}
②不带头结点
bool DeleteNode(LNode *p, ElemType &e){
LNode *q = L;
if(p == q){
L = p -> next;
free(p);
return true;
}
while(q -> next != q)
q = q -> next;
return DeleteNextNode(q, e);
}
时间复杂度:O(n)
方案2:将p结点的后继结点赋予自身,删除后继结点
有无头结点相同
bool DeleteNode(LNode *p, ElemType &e){
if(p == NULL )
return false;
e = p -> data;
LNode *q = p -> next;
if(q == NULL )
free(p);
return true;
p -> data = q -> data;
p -> next = q -> next;
free(q);
return true;
}
时间复杂度:O(1)
7.求表长
①带头结点
int Length(LinkList L){
int len = 0;
if(L == NULL)
return false;
while(L->next){
len++;
L = L -> next;
}
return len;
}
②不带头结点
int Length(LinkList L){
int len = 0;
if(L == NULL)
return false;
while(L){
len++;
L = L -> next;
}
return len;
}
时间复杂度:O(n)
7.销毁
有无头结点相同
void DestroyList(LinkList &L){
LNode *q;
while(L){
q = L;
L= L -> next
free(q);
}
L = NULL;
}
时间复杂度:O(n)