单链表-无头结点
- 1.头文件及类型定义
- 2.单链表结点类型定义
- 3.函数声明
- 4.基本操作
-
- 4.1 初始化单链表
- 4.2 判空
- 4.3 插入操作
-
- 4.3.1 按位插入
- 4.3.2 指定结点插入
-
- 4.3.2.1 指定结点后插
- 4.3.2.2 指定结点前插
-
- 4.3.2.2.1 前插法1(时间复杂度为O(n))
- 4.3.2.2.2 前插法2(时间复杂度为O(1))
- 4.4 删除操作
-
- 4.4.1 按位删除
- 4.4.2 指定结点删除
-
- 4.4.2.1 删除法1(时间复杂度为O(n))
- 4.4.2.2 删除法2(时间复杂度为O(1))
- 4.5 查找操作
-
- 4.6 求表长
- 4.7 创建单链表
-
- 4.7.1 头插法
- 4.7.2 尾插法
-
- 4.7.2.1 依次查找(时间复杂度为O(n^2))
- 4.7.2.2 尾指针(时间复杂度为O(n))
- 4.8 遍历
- 4.9 main函数
- 5.小结
1.头文件及类型定义
#include<stdio.h>
#include<stdlib.h>
#define ElemType int
2.单链表结点类型定义
typedef struct LNode {
ElemType data;
struct LNode* next;
}LNode,*LinkList;
3.函数声明
LinkList InitList(LinkList& L);
bool Empty(LinkList L);
bool InsertList(LinkList& L, int i, ElemType e);
bool InsertNextNode(LNode* p, ElemType e);
bool InsertPriorNode1(LinkList& L, LNode* p, ElemType e);
bool InsertPriorNode2(LNode* p, ElemType e);
bool ListDelete(LinkList& L, int i, ElemType& e);
bool DeleteNode1(LinkList& L, LNode* p);
bool DeleteNode2(LNode* p);
LNode* GetElem(LinkList L, int i);
LNode* LocateElem(LinkList L, ElemType e);
int Length(LinkList L);
LinkList List_TailInsert1(LinkList& L);
LinkList List_TailInsert2(LinkList& L);
LinkList List_HeadInsert(LinkList& L);
void PrintList(LinkList L);
4.基本操作
4.1 初始化单链表
LinkList InitList(LinkList& L) {
L = NULL;
return L;
}
4.2 判空
bool Empty(LinkList L) {
if (L == NULL)
return true;
else
return false;
}
4.3 插入操作
4.3.1 按位插入
bool InsertList(LinkList& L, int i, ElemType e) {
if (i == 1) {
LNode* s = (LNode*)malloc(sizeof(LNode));
if (s == NULL)
return false;
s->data = e;
s->next = L;
L = s;
return true;
}
LNode* p = GetElem(L, i - 1);
return InsertNextNode(p, e);
}
4.3.2 指定结点插入
4.3.2.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;
}
4.3.2.2 指定结点前插
4.3.2.2.1 前插法1(时间复杂度为O(n))
bool InsertPriorNode1(LinkList& L, LNode* p, ElemType e) {
if (p == NULL)
return false;
if (p == L) {
LNode* s = (LNode*)malloc(sizeof(LNode));
if (s == NULL)
return false;
s->data = e;
s->next = L;
L = s;
return true;
}
LNode* q;
q = L;
while (q != NULL && q->next != p)
q = q->next;
if (q == NULL)
return false;
LNode* s = (LNode*)malloc(sizeof(LNode));
if (s == NULL)
return false;
s->data = e;
s->next = q->next;
q->next = s;
return true;
}
4.3.2.2.2 前插法2(时间复杂度为O(1))
bool InsertPriorNode2(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;
}
4.4 删除操作
4.4.1 按位删除
bool ListDelete(LinkList& L, int i, ElemType& e) {
if (i == 1) {
LNode* p;
p = L;
e = p->data;
L = p->next;
free(p);
return true;
}
if (i < 1)
return false;
LNode* p = GetElem(L, i - 1);
if (p == NULL)
return false;
if (p->next == NULL)
return false;
LNode* q = p->next;
e = q->data;
p->next = q->next;
free(q);
return true;
}
4.4.2 指定结点删除
4.4.2.1 删除法1(时间复杂度为O(n))
bool DeleteNode1(LinkList& L, LNode* p) {
if (p == NULL)
return false;
if (L == p) {
L = p->next;
free(p);
return true;
}
LNode* q;
q = L;
while (q != NULL && q->next != p)
q = q->next;
if (q == NULL)
return false;
q->next = p->next;
free(p);
return true;
}
4.4.2.2 删除法2(时间复杂度为O(1))
bool DeleteNode2(LNode* p) {
if (p == NULL)
return false;
LNode* q = p->next;
p->data = q->data;
p->next = q->next;
free(q);
return true;
}
4.5 查找操作
4.5.1 按位查找
LNode* GetElem(LinkList L, int i) {
if (i < 0)
return NULL;
LNode* p = L;
int j = 1;
while (p != NULL && j < i) {
p = p->next;
j++;
}
return p;
}
4.5.2 按值查找
LNode* LocateElem(LinkList L, ElemType e) {
LNode* p = L;
while (p != NULL && p->data != e)
p = p->next;
return p;
}
4.6 求表长
int Length(LinkList L) {
int len = 1;
LNode* p = L;
while (p->next != NULL) {
p = p->next;
len++;
}
return len;
}
4.7 创建单链表
4.7.1 头插法
LinkList List_HeadInsert(LinkList& L) {
L = InitList(L);
ElemType x;
LNode* s;
int i = 1;
printf("开始创建单链表!\n请输入第%d个元素:", i);
scanf("%d", &x);
while (x != 0) {
s = (LNode*)malloc(sizeof(LNode));
s->data = x;
s->next = L;
L = s;
printf("成功插入第%d个元素:%d\n", i,x);
printf("请输入%d个元素:", ++i);
scanf("%d", &x);
}
return L;
}
4.7.2 尾插法
4.7.2.1 依次查找(时间复杂度为O(n^2))
LinkList List_TailInsert1(LinkList& L) {
InitList(L);
int length = 0;
ElemType x;
scanf("%d", &x);
while (x != 0) {
InsertList(L, length + 1, x);
length++;
scanf("%d", &x);
}
return L;
}
4.7.2.2 尾指针(时间复杂度为O(n))
LinkList List_TailInsert2(LinkList& L) {
ElemType x;
L = InitList(L);
int i = 1;
LNode* s, * r = L;
scanf("%d", &x);
while (x != 0) {
s = (LNode*)malloc(sizeof(LNode));
if (i == 1) {
s->data = x;
L = s;
r = s;
i = 0;
scanf("%d", &x);
continue;
}
s->data = x;
r->next = s;
r = s;
scanf("%d", &x);
}
r->next = NULL;
return L;
}
4.8 遍历
void PrintList(LinkList L) {
LNode* p;
p = L;
printf("遍历单链表:\n");
while (p != NULL) {
printf("%d\t", p->data);
p = p->next;
}
printf("\n");
}
4.9 main函数
int main() {
LinkList L;
int i;
L = List_HeadInsert(L);
printf("当前表长为:%d\n", Length(L));
PrintList(L);
ElemType e1;
printf("请输入您所要插入的位序i和元素值e:");
scanf("%d%d", &i, &e1);
if (InsertList(L, i, e1))
printf("您已成功插入元素值:%d\n", e1);
else
printf("位序i不合法,插入元素值%d失败!\n", e1);
PrintList(L);
ElemType e2 = -1;
printf("请输入您所要删除的位序i:");
scanf("%d", &i);
if (ListDelete(L, i, e2))
printf("您已成功删除元素值:%d\n", e2);
else
printf("位序%d不合法,元素删除失败!\n", i);
PrintList(L);
printf("请输入您要查找的位序i:");
scanf("%d", &i);
LNode* p1 = GetElem(L, i);
printf("位序为%d的值为:%d\n", i, p1->data);
ElemType e3;
printf("请输入您要后插的值:");
scanf("%d", &e3);
if (InsertNextNode(p1, e3))
printf("p结点后插成功,元素值为:%d\n", e3);
else
printf("p结点后插失败!\n");
PrintList(L);
ElemType e4;
printf("请输入您要前插的值::");
scanf("%d", &e4);
if (InsertPriorNode1(L, p1, e4))
printf("p结点前插成功,元素值为:%d\n", e4);
else
printf("p结点前插失败\n");
PrintList(L);
ElemType e5;
printf("请输入您要查找的元素值e:");
scanf("%d", &e5);
LNode* p2 = LocateElem(L, e5);
if (DeleteNode1(L, p2))
printf("值为%d的元素删除成功!\n", e5);
else
printf("值为%d的元素删除失败!\n", e5);
PrintList(L);
return 0;
}
5.小结
- 在对无头结点的单链表进行操作时,很多操作要单独考虑操作对象是第一个结点的情况,因此需要专门设置一段逻辑来处理。为了避免这种情况,引入带头结点的单链表(所有结点的处理逻辑均相同)。