链表和数组的区别:
两者的区别:
数组静态分配内存,链表动态分配内存。
数组在内存中是连续的,链表是不连续的。
数组利用下标定位,查找的时间复杂度是O(1),链表通过遍历定位元素,查找的时间复杂度是O(N)。
数组插入和删除需要移动其他元素,时间复杂度是O(N),链表的插入或删除不需要移动其他元素,时间复杂度是O(1)。
数组的优点
随机访问性比较强,可以通过下标进行快速定位。
查找速度快
数组的缺点
插入和删除的效率低,需要移动其他元素。
会造成内存的浪费,因为内存是连续的,所以在申请数组的时候就必须规定七内存的大小,如果不合适,就会造成内存的浪费。
内存空间要求高,创建一个数组,必须要有足够的连续内存空间。
数组的大小是固定的,在创建数组的时候就已经规定好,不能动态拓展。
链表的优点
插入和删除的效率高,只需要改变指针的指向就可以进行插入和删除。
内存利用率高,不会浪费内存,可以使用内存中细小的不连续的空间,只有在需要的时候才去创建空间。大小不固定,拓展很灵活。
链表的缺点
查找的效率低,因为链表是从第一个节点向后遍历查找。
LinkList.h代码
#pragma once
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef __cplusplus
extern "C"{
#endif // _cplusplus
typedef void* LinkList;
typedef void(*FOREACH)(void *);
//比较函数
typedef int(*COMPARE)(void *,void *);
//初始化链表
LinkList Init_LinkLList();
//插入节点
void Insert_LinkList(LinkList list,int pos,void *data);
//遍历链表
void Foreach_LinkList(LinkList list,FOREACH myForeach);
//按位置删除
void RemoveByPos_LinkList(LinkList list, int pos);
//按值删除
void RemoveByVal_LinkList(LinkList list, void* data,COMPARE compare);
//清空链表
void Clear_LinkList(LinkList list);
//大小
int Size_LinkList(LinkList list);
//销毁链表
void Destroy_LinkList(LinkList list);
#ifdef __cplusplus
}
#endif
linkList.c代码
#include "LinkList.h"
//链表节点数据类型
struct LinkNode
{
void* data;//数据域
struct LinkNode* next;
};
//链表数据类型
struct LList
{
struct LinkNode header;
int size;
};
//初始化链表
LinkList Init_LinkLList()
{
struct LList * list = malloc(sizeof(struct LList));
if (NULL == list)
{
return NULL;
}
list->header.data = NULL;
list->header.next = NULL;
list->size = 0;
return list;
}
//插入节点
void Insert_LinkList(LinkList list, int pos, void* data)
{
if (NULL == list || data == NULL)
{
return;
}
//强制转换一下
struct LList* myList = (struct LList*)list;
if (pos<0 || pos >myList->size)
{
pos = myList->size;
}
//查找插入位置 取到头节点地址
struct LinkNode* pCurrent = &(myList->header);
for (int i = 0; i < pos;++i)
{
pCurrent = pCurrent->next;
}
//创建新节点
struct LinkNode* newnode = malloc(sizeof(struct LinkNode));
newnode->data = data;
newnode->next = NULL;
//新节点插入到链表中
newnode->next = pCurrent->next;
pCurrent->next = newnode;
myList->size++;
}
//遍历链表
void Foreach_LinkList(LinkList list, FOREACH myForeach)
{
if (NULL == list || NULL == myForeach)
{
return;
}
struct LList* myList = (struct LList*)list;
struct LinkNode* pCurrent = myList->header.next;
while (pCurrent!=NULL)
{
//访问当前节点的数据域
myForeach(pCurrent->data);
pCurrent = pCurrent->next;
}
}
//按位置删除
void RemoveByPos_LinkList(LinkList list, int pos)
{
if (list == NULL)
{
return;
}
struct LList* myList = (struct LList*)list;
if (pos < 0|| pos > myList->size-1)
{
return;
}
//找位置
struct LinkNode *pCurrent = &(myList->header);
for (int i = 0; i < pos;++i)
{
pCurrent = pCurrent->next;
}
//先保存带删除结点
struct LinkNode *pDel = pCurrent->next;
//重新建立带删除结点的前驱和后继结点关系
pCurrent->next = pDel->next;
//释放删除节点内存
free(pDel);
pDel = NULL;
myList->size--;
}
//按值删除
void RemoveByVal_LinkList(LinkList list, void* data, COMPARE compare)
{
if (list == NULL || data==NULL || compare == NULL)
{
return;
}
//转换类型
struct LList* myList = (struct LList*)list;
//辅助指针变量
struct LinkNode *pPrev = &(myList->header);
struct LinkNode *pCurrent = pPrev->next;
while (pCurrent!=NULL)
{
if (compare(pCurrent->data,data))
{
//找到了
pPrev->next = pCurrent->next; //指向删除节点的下一个节点
//释放删除节点内存
free(pCurrent);
pCurrent = NULL;
myList->size--;
break;
}
pPrev = pCurrent;
pCurrent = pCurrent->next;
}
}
//清空链表
void Clear_LinkList(LinkList list)
{
if (list == NULL)
{
return;
}
struct LList* myList = (struct LList*)list;
//辅助指针变量
struct LinkNode *pCurrent = myList->header.next;
while (pCurrent!=NULL)
{
struct LinkNode *pNext = pCurrent->next;
//释放当前节点内存
free(pCurrent);
pCurrent = pNext;
}
myList->header.next = NULL;
myList->size = 0;
}
//大小
int Size_LinkList(LinkList list)
{
if (list == NULL)
{
return;
}
struct LList* myList = (struct LList*)list;
return myList->size;
}
//销毁链表
void Destroy_LinkList(LinkList list)
{
if (list == NULL)
{
return;
}
//清空链表
Clear_LinkList(list);
free(list);
list = NULL;
}
主函数代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "LinkList.h"
struct Person
{
char name[64];
int age;
};
void MyPrint(void *data)
{
struct Person* person = (struct Person*)data;
printf("Name:%s,Age:%d\n", person->name, person->age);
}
int MyComapre(void *d1, void *d2)
{
struct Person* p1 = (struct Person*)d1;
struct Person* p2= (struct Person*)d2;
/*if (strcmp(p1->name,p2->name)==0 && p1->age==p2->age)
{
return 1;
}
return 0;*/
return strcmp(p1->name, p2->name) == 0 && p1->age == p2->age;
}
void text()
{
//创建链表
LinkList list = Init_LinkLList();
//创建数据
struct Person p1 = { "aaa",10 };
struct Person p2 = { "bbb",20 };
struct Person p3 = { "ccc",30 };
struct Person p4 = { "ddd",40 };
struct Person p5 = { "eee",50 };
struct Person p6 = { "fff",60 };
struct Person p7= { "ggg",70 };
//插入数据
Insert_LinkList(list, 0, &p1);
Insert_LinkList(list, 0, &p2);
Insert_LinkList(list, 1, &p3);
Insert_LinkList(list, 2, &p4);
Insert_LinkList(list, 20, &p5);
Insert_LinkList(list, 3, &p6);
Insert_LinkList(list, 6, &p7);
//遍历
Foreach_LinkList(list, MyPrint);
printf("-------------\n");
printf("List Size :%d\n",Size_LinkList(list));
RemoveByPos_LinkList(list, 3);
//遍历
Foreach_LinkList(list, MyPrint);
printf("-------------\n");
struct Person pDl = { "ggg", 70 };
RemoveByVal_LinkList(list, &pDl, MyComapre);
//遍历
Foreach_LinkList(list, MyPrint);
printf("-------------\n");
//清空链表
Clear_LinkList(list);
printf("-------------\n");
printf("List Size :%d\n", Size_LinkList(list));
}
int main()
{
text();
system("pause");
return 0;
}