一、数据结构与算法-单向链表
??优点:删除和插入方便。 ??缺点:查找某元素时需遍历链表中的所有结点。
1.1 简单单向链表
?? 1.1.1 简单链表的存储结构
???? 简单单向链表的存储结构如下图所示,
?? 1.1.2 在链表指定位置处插入元素
???? 具体步骤如下所示: ???? ?? 1) 创建指向头结点的辅助结点(LinkNode *pCurrent) ???? ?? 2) 将辅助结点移动至指定位置处 ???? ?? 3) 插入元素;注意:插入元素时需要新开辟结点(LinkNode *newNode)存放需要插入的数据。 ???? 插入步骤如下图所示,
???? 实现代码如下所示:
void Insert_LinkList(LinkList* list, void* data, int pos) {
if (list == NULL || data == NULL) return;
if (pos < 0 || pos>list->size) pos = list->size;
LinkNode* pCurrentLinkNode = list->head;
for (int i = 0; i < pos; i++) {
pCurrentLinkNode = pCurrentLinkNode->next;
}
LinkNode* newNode = (LinkNode*)malloc(sizeof(LinkNode));
newNode->data = data;
newNode->next = pCurrentLinkNode->next;
pCurrentLinkNode->next = newNode;
list->size++;
}
?? 1.1.3 在指定位置删除元素
???? 具体步骤如下所示: ???? ?? 1) 创建指向头结点的辅助结点(LinkNode pCurrent) ???? ?? 2) 将辅助结点移动至指定位置处 ???? ?? 3) 删除结点中的元素;注意:删除元素时需要创建一个指向被删除结点的临时指针(tempNode),结点中元素删除完毕后,需要释放该结点所占用的内存,否则会造成内存泄漏。 ???? 删除步骤如下图所示,
void RemoveValueByPos_LinkList(LinkList* list, int pos) {
if (list == NULL) return;
if (pos < 0 || pos>list->size) return;
LinkNode* pCurrentLinkNode = list->head;
for (int i = 0; i < pos; i++) {
pCurrentLinkNode = pCurrentLinkNode->next;
}
LinkNode* newNode = pCurrentLinkNode->next;
pCurrentLinkNode->next = newNode->next;
free(newNode);
list->size--;
}
?? 1.1.4 完整代码
#ifndef LINKLIST_H
#define LINKLIST_H
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
typedef void (*PRINT)(void*);
typedef int (*COMPARE)(void*, void*);
typedef struct LINKNODE {
void* data;
struct LINKNODE* next;
}LinkNode;
typedef struct LINKLIST {
LinkNode* head;
int size;
}LinkList;
LinkList* Init_LinkList();
void Insert_LinkList(LinkList* list, void* data, int pos);
void RemoveValueByPos_LinkList(LinkList* list, int pos);
void RemoveValueByValue_LinkList(LinkList* list, void* data, COMPARE compare);
int Find_LinkList(LinkList* list, void* data, COMPARE compare);
void* Front_LinkLsit(LinkList* list);
int Size_LinkList(LinkList* list);
void Print_LinkList(LinkList* list, PRINT print);
void FreeSpace_LinkList(LinkList* list);
#endif
#include"LinkList.h"
LinkList* Init_LinkList() {
LinkList* list = (LinkList*)malloc(sizeof(LinkList));
if (list != NULL) {
list->size = 0;
list->head = (LinkNode*)malloc(sizeof(LinkNode));
if (list->head != NULL) {
list->head->data = NULL;
list->head->next = NULL;
}
}
else {
printf("内存分配失败!");
return NULL;
}
return list;
}
void Insert_LinkList(LinkList* list, void* data, int pos) {
if (list == NULL || data == NULL) return;
if (pos < 0 || pos>list->size) pos = list->size;
LinkNode* pCurrentLinkNode = list->head;
for (int i = 0; i < pos; i++) {
pCurrentLinkNode = pCurrentLinkNode->next;
}
LinkNode* newNode = (LinkNode*)malloc(sizeof(LinkNode));
newNode->data = data;
newNode->next = pCurrentLinkNode->next;
pCurrentLinkNode->next = newNode;
list->size++;
}
void RemoveValueByPos_LinkList(LinkList* list, int pos) {
if (list == NULL) return;
if (pos < 0 || pos>list->size) return;
LinkNode* pCurrentLinkNode = list->head;
for (int i = 0; i < pos; i++) {
pCurrentLinkNode = pCurrentLinkNode->next;
}
LinkNode* newNode = pCurrentLinkNode->next;
pCurrentLinkNode->next = newNode->next;
free(newNode);
list->size--;
}
void RemoveValueByValue_LinkList(LinkList* list, void* data, COMPARE compare) {
if (list == NULL || data == NULL) return;
LinkNode* pCurrent = list->head;
while (pCurrent) {
if (compare(pCurrent->next->data, data) == 1) {
LinkNode* newNode = pCurrent->next;
pCurrent->next = newNode->next;
free(newNode);
list->size--;
return;
}
pCurrent = pCurrent->next;
}
}
int Find_LinkList(LinkList* list, void* data, COMPARE compare) {
if (list == NULL || data == NULL) return -1;
LinkNode* pCurrent = list->head->next;
int pos = 0, flag = -1;
while (pCurrent) {
if (compare(pCurrent->data, data) == 1) {
return flag = pos;
}
pos++;
pCurrent = pCurrent->next;
}
return flag;
}
void* Front_LinkLsit(LinkList* list) {
if (list == NULL) return NULL;
return list->head->next->data;
}
int Size_LinkList(LinkList* list) {
if (list == NULL) return -1;
return list->size;
}
void Print_LinkList(LinkList* list, PRINT print) {
if (list == NULL) return;
LinkNode* pCurrent = list->head->next;
while (pCurrent) {
print(pCurrent->data);
pCurrent = pCurrent->next;
}
}
void FreeSpace_LinkList(LinkList* list) {
if (list == NULL) return;
LinkNode* pCurrent = list->head;
while (pCurrent) {
LinkNode* pNext = pCurrent->next;
free(pCurrent);
pCurrent = pNext->next;
}
free(list);
}
#include"LinkList.h"
#include<string.h>
#define MAX_NUM 10
typedef struct PERSON {
char name[64];
int age;
}Person;
void myPrint(void* data) {
Person* p = (Person*)data;
printf("姓名:%s,年龄:%d\n", p->name, p->age);
}
int compare(void* data1, void* data2) {
Person* p1 = (Person*)data1;
Person* p2 = (Person*)data2;
if (!strcmp(p1->name, p2->name) && p1->age == p2->age) return 1;
return -1;
}
int main() {
Person p1 = { "aaa", 20 }, p2 = { "bbb", 30 }, p3 = { "ccc", 40 }, p4 = { "ddd", 50 }, p5 = {"eee", 60};
LinkList* list = Init_LinkList();
Insert_LinkList(list, &p1, 0);
Insert_LinkList(list, &p2, 0);
Insert_LinkList(list, &p3, 0);
Insert_LinkList(list, &p4, 0);
Insert_LinkList(list, &p5, 0);
printf("删除结点前的链表:\n");
Print_LinkList(list, myPrint);
RemoveValueByPos_LinkList(list, 0);
printf("删除0号结点后的链表:\n");
Print_LinkList(list, myPrint);
Person p6 = { "aaa", 20 };
RemoveValueByValue_LinkList(list, &p6, compare);
printf("删除数据为{name:aaa, age: 20}的结点后的链表:\n");
Print_LinkList(list, myPrint);
printf("{name:ccc, age: 40}所在位置:%d\n", Find_LinkList(list, &p3, compare));
printf("\n=====================\n");
printf("链表中元素个数:%d\n", Size_LinkList(list));
Person* ret = (Person*)Front_LinkLsit(list);
printf("姓名:%s, 年龄:%d", ret->name, ret->age);
FreeSpace_LinkList(list);
return 0;
}
?? 1.1.5 运行结果
???? 运行结果如下所示,
1.2 改进后的链表
?? 1.2.1 改进链表的存储结构
??改进后的链表结点(LinkNode)仅包含指针域(LinkNode *next),无数据域。用链表维(LinkList)护链表结点(LinkNode)和元素数量(size)。链表结构如下所示, ??值得注意的是,放入链表中的数据必须包含一个链表结点,通过链表结点将数据串联串联,具体如下所示。 ??相较于1.1小节的链表,改进后的链表在插入元素无需开辟新结点存储数据,仅需改变结点的next指针即可。
?? 1.2.2 向改进后的链表插入元素
??向改进后的链表插入元素如下图所示,
void Insert_LinkList(LinkList* list, LinkNode* node, int pos) {
if (list == NULL || node == NULL) return;
if (pos < 0 || pos >list->size) pos = list->size;
LinkNode* pCurrent = &list->head;
for (int i = 0; i < pos; i++) {
pCurrent = pCurrent->next;
}
node->next = pCurrent->next;
pCurrent->next = node;
list->size++;
}
二、参考链接
???1、数据结构与算法知识点总结 ???2、C++教程
|