1
0
mirror of https://github.com/Didnelpsun/CS408.git synced 2026-10-31 04:14:52 +08:00

更新单链表

This commit is contained in:
Didnelpsun
2021-04-18 23:47:07 +08:00
parent 5dc7cff126
commit 09f80d310c
3 changed files with 374 additions and 8 deletions

View File

@@ -158,4 +158,186 @@ int InsertPriorLinkNode(LinkNode* node, element_type elem) {
s->data = node->data;
node->data = elem;
return 0;
}
// 删除有头节点单链表元素
int DeleteLinkListWithHead(LinkList list, int index, element_type *elem) {
if (index < 1) {
printf("DeleteLinkListWithHead:删除索引值过小!\n");
return 1;
}
// p指向当前扫描的结点
LinkNode* p;
// i表示当前指向的是第几个结点
int i = 0;
// 指向头结点
p = list;
while (p != NULL && i < index - 1) {
p = p->next;
i++;
}
if (p == NULL || p->next == NULL) {
printf("DeleteLinkListWithHead:删除索引值过大!\n");
return 1;
}
// q指向被删除的结点
LinkNode* q = p->next;
// 获取删除的元素数据
*elem = q->data;
// 将q结点从链表中断开
p->next = q->next;
free(q);
return 0;
}
// 删除无头节点单链表元素
int DeleteLinkListWithHead(LinkList list, int index, element_type* elem) {
if (index < 0) {
printf("DeleteLinkListWithHead:删除索引值过小!\n");
return 1;
}
// p指向当前扫描的结点
LinkNode* p;
// i表示当前指向的是第几个结点
int i = 0;
// 指向头结点
p = list;
// 如果删除第一个第0号结点
if (index == 0) {
list = p->next;
free(p);
return 0;
}
while (p != NULL && i < index - 1) {
p = p->next;
i++;
}
if (p == NULL || p->next == NULL) {
printf("DeleteLinkListWithHead:删除索引值过大!\n");
return 1;
}
// q指向被删除的结点
LinkNode* q = p->next;
// 获取删除的元素数据
*elem = q->data;
// 将q结点从链表中断开
p->next = q->next;
free(q);
return 0;
}
// 删除单链表元素
int DeleteLinkNode(LinkNode* node) {
if (node == NULL) {
printf("DeleteLinkNode:本结点是空结点无法删除!");
return 1;
}
// 如果该结点为最后一个结点,无法找到前驱结点,无法操作
if (node->next = NULL) {
printf("DeleteLinkNode:后继结点为空无法操作!");
return 1;
}
// 指向后继结点
LinkNode* p = node->next;
// 交换数据
node->data = p->data;
// 断开结点
node->next = p->next;
free(p);
return 0;
}
// 按位查找单链表元素
element_type GetLinkListElement(LinkList list, int index) {
if (index < 0) {
printf("GetLinkListElement:查找索引值过小!\n");
return NULL;
}
// 定义一个结点指针p指向当前扫描到的结点
LinkNode* p;
// 定义一个变量i表示当前扫描到的结点的索引号
int i = 0;
// 将链表头结点指向p,为第0个结点
p = list;
// 循环遍历到达指定索引号的单链表的结点
// 条件是当前结点的下一个不为空且索引号到达,所到达的结点一定不是空结点
while (p->next != NULL && i < index) {
p = p->next;
i++;
}
// 如果查找索引大于当前扫描索引
if (i < index) {
printf("GetLinkListElement:查找索引值过大!\n");
return NULL;
}
return p->data;
}
// 按位查找单链表结点
LinkNode* GetLinkListNode(LinkList list, int index) {
if (index < 0) {
printf("GetLinkListNode:查找索引值过小!\n");
return NULL;
}
// 定义一个结点指针p指向当前扫描到的结点
LinkNode* p;
// 定义一个变量i表示当前扫描到的结点的索引号
int i = 0;
// 将链表头结点指向p,为第0个结点
p = list;
// 循环遍历到达指定索引号的单链表的结点
// 条件是当前结点的下一个不为空且索引号到达,所到达的结点一定不是空结点
while (p->next != NULL && i < index) {
p = p->next;
i++;
}
// 如果查找索引大于当前扫描索引
if (i < index) {
printf("GetLinkListNode:查找索引值过大!\n");
}
// 如果索引值过大,其p也会指向最后一个NULL,所以返回值都是一样为NULL,不需要单独处理
return p;
}
// 按值查找单链表结点
LinkNode* LocateLinkListNode(LinkList list, element_type elem) {
LinkNode* p = list;
while (p != NULL && p->data != elem) {
p = p->next;
}
return p;
}
// 求链表长度
int GetLength(LinkList list) {
int len = 0;
LinkNode* p = list;
while (p->next != NULL) {
p = p->next;
len++;
}
return len;
}
// 后插建立带头节点单链表
LinkList TailBuildLinkListWithHead(LinkList* list, int length) {
element_type elem;
list = (LinkList)malloc(sizeof(LinkNode));
// s指针为一个中间变量指针,r指针为尾指针(next指向最后一个元素)
LinkNode* s, * r = list;
int i = 0;
element_type x;
if (length < 1) {
printf("TailBuildLinkListWithHead:输入的单链表长度过小!");
return 1;
}
while (i < length) {
scanf("%d", &x);
s = (LinkNode*)malloc(sizeof(LinkNode));
s->data = x;
r->next = s;
r = s;
i++;
}
}

View File

@@ -172,25 +172,25 @@ int DeleteDynamicSequenceList(DynamicSequenceList* list, int index, element_type
return 0;
}
// 按位获取静态顺序表元素
// 按位查找静态顺序表元素
element_type GetStaticSequenceListElement(StaticSequenceList list, int index) {
if (index >= list.length || index < 0) {
printf("GetStaticSequenceListElement:查找索引超过索引范围!\n");
return 1;
return NULL;
}
return list.data[index];
}
// 按位获取动态顺序表元素
// 按位查找动态顺序表元素
element_type GetDynamicSequenceListElement(DynamicSequenceList list, int index) {
if (index >= list.length || index < 0) {
printf("GetDynamicSequenceListElement:查找索引超过索引范围!\n");
return 1;
return NULL;
}
return list.data[index];
}
// 按值获取静态顺序表索引
// 按值查找静态顺序表索引
int LocateStaticSequenceListElement(StaticSequenceList list, element_type elem) {
for (int i = 0; i < list.length; i++) {
if (list.data[i] == elem) {
@@ -201,7 +201,7 @@ int LocateStaticSequenceListElement(StaticSequenceList list, element_type elem)
return -1;
}
// 按值获取动态顺序表索引
// 按值查找动态顺序表索引
int LocateDynamicSequenceListElement(DynamicSequenceList list, element_type elem) {
for (int i = 0; i < list.length; i++) {
if (list.data[i] == elem) {

View File

@@ -243,7 +243,7 @@ int DeleteDynamicSequenceList(DynamicSequenceList* list, int index, element_type
element_type GetStaticSequenceListElement(StaticSequenceList list, int index) {
if (index >= list.length || index < 0) {
printf("GetStaticSequenceListElement:查找索引超过静态顺序表索引范围!\n");
return 1;
return NULL;
}
return list.data[index];
}
@@ -254,7 +254,7 @@ element_type GetStaticSequenceListElement(StaticSequenceList list, int index) {
element_type GetDynamicSequenceListElement(DynamicSequenceList list, int index) {
if (index >= list.length || index < 0) {
printf("GetDynamicSequenceListElement:查找索引超过动态态顺序表索引范围!\n");
return 1;
return NULL;
}
return list.data[index];
}
@@ -496,3 +496,187 @@ int InsertPriorLinkNode(LinkNode* node, element_type elem) {
return 0;
}
```
#### 单链表删除
基本的方式和插入类似,都是转移next结点。
带头结点的也只能删除从1开始的结点,0的头结点不能删除。
时间复杂度为$O(n)$。
```c
// 删除有头节点单链表元素
int DeleteLinkListWithHead(LinkList list, int index, element_type *elem) {
if (index < 1) {
printf("DeleteLinkListWithHead:删除索引值过小!\n");
return 1;
}
// p指向当前扫描的结点
LinkNode* p;
// i表示当前指向的是第几个结点
int i = 0;
// 指向头结点
p = list;
while (p != NULL && i < index - 1) {
p = p->next;
i++;
}
if (p == NULL || p->next == NULL) {
printf("DeleteLinkListWithHead:删除索引值过大!\n");
return 1;
}
// q指向被删除的结点
LinkNode* q = p->next;
// 获取删除的元素数据
*elem = q->data;
// 将q结点从链表中断开
p->next = q->next;
free(q);
return 0;
}
```
无头结点需要额外处理第一个结点
```c
// 删除无头节点单链表元素
int DeleteLinkListWithHead(LinkList list, int index, element_type* elem) {
if (index < 0) {
printf("DeleteLinkListWithHead:删除索引值过小!\n");
return 1;
}
// p指向当前扫描的结点
LinkNode* p;
// i表示当前指向的是第几个结点
int i = 0;
// 指向头结点
p = list;
// 如果删除第一个第0号结点
if (index == 0) {
list = p->next;
free(p);
return 0;
}
while (p != NULL && i < index - 1) {
p = p->next;
i++;
}
if (p == NULL || p->next == NULL) {
printf("DeleteLinkListWithHead:删除索引值过大!\n");
return 1;
}
// q指向被删除的结点
LinkNode* q = p->next;
// 获取删除的元素数据
*elem = q->data;
// 将q结点从链表中断开
p->next = q->next;
free(q);
return 0;
}
```
如果删除指定结点而不知道其前驱,也可以使用之前前插结点的方式,把该结点后继的结点的数据复制到本结点上,然后把后继结点删除,就相当于删除了本结点。时间复杂度为$O(1)$。
```c
// 删除单链表元素
int DeleteLinkNode(LinkNode* node) {
if (node == NULL) {
printf("DeleteLinkNode:本结点是空结点无法删除!");
return 1;
}
// 如果该结点为最后一个结点,无法找到前驱结点,无法操作
if (node->next = NULL) {
printf("DeleteLinkNode:后继结点为空无法操作!");
return 1;
}
// 指向后继结点
LinkNode* p = node->next;
// 交换数据
node->data = p->data;
// 断开结点
node->next = p->next;
free(p);
return 0;
}
```
所以单链表还是不算方便。
#### 单链表查找
按位查找时间复杂度为$O(n)$。
```c
// 按位查找单链表元素
element_type GetLinkListElement(LinkList list, int index) {
if (index < 0) {
printf("GetLinkListElement:查找索引值过小!\n");
return NULL;
}
// 定义一个结点指针p指向当前扫描到的结点
LinkNode* p;
// 定义一个变量i表示当前扫描到的结点的索引号
int i = 0;
// 将链表头结点指向p,为第0个结点
p = list;
// 循环遍历到达指定索引号的单链表的结点
// 条件是当前结点的下一个不为空且索引号到达,所到达的结点一定不是空结点
while (p->next != NULL && i < index) {
p = p->next;
i++;
}
// 如果查找索引大于当前扫描索引
if (i < index) {
printf("GetLinkListElement:查找索引值过大!\n");
return NULL;
}
return p->data;
}
```
```c
// 按位查找单链表结点
LinkNode* GetLinkListNode(LinkList list, int index) {
if (index < 0) {
printf("GetLinkListNode:查找索引值过小!\n");
return NULL;
}
// 定义一个结点指针p指向当前扫描到的结点
LinkNode* p;
// 定义一个变量i表示当前扫描到的结点的索引号
int i = 0;
// 将链表头结点指向p,为第0个结点
p = list;
// 循环遍历到达指定索引号的单链表的结点
// 条件是当前结点的下一个不为空且索引号到达,所到达的结点一定不是空结点
while (p->next != NULL && i < index) {
p = p->next;
i++;
}
// 如果查找索引大于当前扫描索引
if (i < index) {
printf("GetLinkListNode:查找索引值过大!\n");
}
// 如果索引值过大,其p也会指向最后一个NULL,所以返回值都是一样为NULL,不需要单独处理
return p;
}
```
这样插入元素函数InsertLinkListWithHead只用`GetLinkListNode(list,i-1)`和`InsertNextLinkNode(p,elem)`两个函数完成。
```c
// 按值查找单链表结点
LinkNode* LocateLinkListNode(LinkList list, element_type elem) {
LinkNode* p = list;
while (p != NULL && p->data != elem) {
p = p->next;
}
return p;
}
```
#### 单链表建立
可以使用尾插法建立单链表,从后面不断插入元素。