概述
线性结构是一种最简单且常用的数据结构。线性结构的基本特点是节点之间满足线性关系。本章讨论的动态数组、链表、栈、队列都属于线性结构。他们的共同之处,是节点中有且只有一个开始节点和终端节点。按这种关系,可以把它们的所有节点排列成一个线性序列。但是,他们分别属于几种不同的抽象数据类型实现,它们之间的区别,主要就是操作的不同。线性表是零个或者多个数据元素的有限序列,数据元素之间是有顺序的,数据元素个数是有限的,数据元素的类型必须相同
单向链表:线性表的链式存储结构中,每个节点中只包含一个指针域,这样的链表叫单链表。通过每个节点的指针域将线性表的数据元素按其逻辑次序链接在一起(如图)。
实现
LinkList.h
#ifndef LINKLIST_H
#define LINKLIST_H
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
//链表节点
typedef struct _LinkNode
{
struct _LinkNode *next;
}LinkNode;
//链表
typedef struct _LinkList
{
LinkNode header;
int size;
}LinkList;
typedef void(DATA_PRINT)(LinkNode*);
typedef int(DATA_COMPARE)(LinkNode*, LinkNode*);
//初始化链表
int init_LinkList(void **list);
//指定位置插入
int insert_LinkList(void *list, int pos, void *data);
//头插
int PushFront_LinkList(void *list, void *data);
//尾插
int PushBack_LinkList(void *list, void *data);
//打印链表
int print_LinkList(void *list, DATA_PRINT* print);
//指定位置删除
int remove_bypos_LinkList(void *list, int pos);
//头部删除
int remove_PushFront_LinkList(void *list);
//尾部删除
int remove_PushBack_LinkList(void *list);
//根据值删除
int remove_byval_LinkList(void *list, void *data, DATA_COMPARE*compare);
//链表大小
int size_LinkList(void *list);
//销毁链表
int free_LinkList(void *list);
#endif
LinkList.c
#include"LinkList.h"
//初始化链表
int init_LinkList(void **list)
{
if (NULL == list)
{
return -1;
}
LinkList *temp = (LinkList *)malloc(sizeof(LinkList));
if (NULL == temp)
{
return -2;
}
temp->header.next = NULL;
temp->size = 0;
*list = temp;
return 0;
}
//指定位置插入
int insert_LinkList(void *list, int pos, void *data)
{
if (NULL == list)
{
return -1;
}
if (NULL == data)
{
return -2;
}
LinkList *temp = (LinkList *)list;
if(pos < 0 || pos > temp->size)
{
pos = temp->size;
}
//辅助指针变量
LinkNode *current = &(temp->header);
for (int i = 0; i < pos; i++)
{
current = current->next;
}
//
LinkNode * newnode = (LinkNode *)data;
//新数据入链表
newnode->next = current->next;
current->next = newnode;
temp->size++;
return 0;
}
//头插
int PushFront_LinkList(void *list, void *data)
{
insert_LinkList(list, 0, data);
return 0;
}
//尾插
int PushBack_LinkList(void *list, void *data)
{
LinkList *temp = (LinkList *)list;
insert_LinkList(list, temp->size, data);
return 0;
}
//打印链表
int print_LinkList(void *list, DATA_PRINT* print)
{
if (NULL == list)
{
return -1;
}
if (NULL == print)
{
return -2;
}
LinkList *temp = (LinkList*)list;
//辅助指针变量
LinkNode* current = temp->header.next;
while (NULL != current)
{
print(current);
current = current->next;
}
return 0;
}
//指定位置删除
int remove_bypos_LinkList(void *list, int pos)
{
if (NULL == list)
{
return -1;
}
LinkList *temp = (LinkList *)list;
if (pos < 0 || pos >= temp->size)
{
return -2;
}
LinkNode *current = &(temp->header);
for (int i = 0; i < pos; i++)
{
current = current->next;
}
//缓冲被删除节点
LinkNode *pdel = current->next;
//待删除节点前驱节点的后继指针指向待删除节点的后继节点
current->next = pdel->next;
temp->size--;
return 0;
}
//头部删除
int remove_PushFront_LinkList(void *list)
{
if (NULL == list)
{
return -1;
}
LinkList *temp = (LinkList *)list;
if (temp->size == 0)
{
return -2;
}
remove_bypos_LinkList(list, 0);
return 0;
}
//尾部删除
int remove_PushBack_LinkList(void *list)
{
if (NULL == list)
{
return -1;
}
LinkList *temp = (LinkList *)list;
if (temp->size == 0)
{
return -2;
}
remove_bypos_LinkList(list, temp->size - 1);
return 0;
}
//根据值删除
int remove_byval_LinkList(void *list, void *data, DATA_COMPARE*compare)
{
if (NULL == list)
{
return -1;
}
if (NULL == data)
{
return -2;
}
if (NULL == compare)
{
return -3;
}
LinkList *temp = (LinkList*)list;
if (temp->size == 0)
{
return -1;
}
//辅助指针变量
LinkNode *prev = &(temp->header);
LinkNode *current = prev->next;
while (current != NULL)
{
if (compare(current, data))
{
prev -> next = current->next;
temp->size--;
break;
}
prev = current;
current = prev->next;
}
return 0;
}
//链表大小
int size_LinkList(void *list)
{
if (NULL == list)
{
return -1;
}
LinkList *temp = (LinkList *)list;
return temp->size;
}
//销毁链表
int free_LinkList(void *list)
{
if (NULL == list)
{
return -1;
}
free(list);
return 0;
}
测试代码
main.c
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include"LinkList.h"
typedef struct _PERSON{
LinkNode node;
char name[64];
int age;
}Person;
void print(LinkNode* curr)
{
if (NULL == curr)
{
return;
}
Person *temp = (Person*)curr;
printf("%s\t%d\n", temp->name, temp->age);
return;
}
int compare(LinkNode* d1, LinkNode* d2)
{
Person * p1 = (Person *)d1;
Person * p2 = (Person *)d2;
if (strcmp(p1->name, p2->name) == 0 && p1->age == p2->age)
{
return 1;
}
return 0;
}
int main()
{
Person p1 = { NULL, "aaa", 10 };
Person p2 = { NULL, "bbb", 20 };
Person p3 = { NULL, "ccc", 30 };
Person p4 = { NULL, "ddd", 40 };
Person p5 = { NULL, "eee", 50 };
Person p6 = { NULL, "fff", 60 };
Person p7 = { NULL, "ggg", 70 };
Person p8 = { NULL, "aaa", 10 };
LinkList *list = NULL;
init_LinkList(&list);
insert_LinkList(list, 10, &p1);
insert_LinkList(list, 10, &p2);
insert_LinkList(list, 10, &p3);
//打印链表
print_LinkList(list, print);
printf("********************************\n");
//头插
PushFront_LinkList(list, &p4);
PushFront_LinkList(list, &p5);
print_LinkList(list, print);
printf("********************************\n");
//尾插
PushBack_LinkList(list, &p6);
PushBack_LinkList(list, &p7);
print_LinkList(list, print);
printf("********************************\n");
//指定位置删除
remove_bypos_LinkList(list, 4);
print_LinkList(list, print);
printf("********************************\n");
//头部删除
remove_PushFront_LinkList(list);
print_LinkList(list, print);
printf("********************************\n");
//尾部删除
remove_PushBack_LinkList(list);
print_LinkList(list, print);
printf("********************************\n根据值删除\n");
//根据值删除
remove_byval_LinkList(list, &p8, compare);
print_LinkList(list, print);
printf("********************************\n");
int len = size_LinkList(list);
printf("链表大小:%d\n", len);
//销毁链表
free_LinkList(list);
system("pause");
return EXIT_SUCCESS;
}