1.线性表
1.1基本概念
线性表是零个或者多个数据元素的有限序列,数据元素之间是有顺序的,数据元素
个数是有限的,数据元素的类型必须相同。
1.2线性表的顺序存储
顺序表是线性表的一种,也就是说,将线性表中的元素一个接一个的存储在一块连
续的存储区域中,这种顺序表示的线性表也成为顺序表。对于线性表来讲,对于线性
表的首结点,只有后继元素没有前驱元素;对于尾结点,只有前驱结点没有后继结点,
其余的结点,既有前驱结点,也有后继结点。
1.3 顺序表的优点和缺点
优点:
无需为线性表中的逻辑关系增加额外的空间。
可以快速的获取表中合法位置的元素。
缺点:
插入和删除操作需要移动大量元素。
1.4 线性表的顺序存储代码实现
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct DynamicArr
{
void** pArr;
int m_capacity;
int m_size;
};
void func(void* a)
{
int* tempInt = a;
printf("%d\n", *tempInt);
}
int deleteValue(void* a1, void* a2)
{
int* a = a1;
int* b = a2;
if (*a == *b)
return 1;
else
return 0;
}
struct DynamicArr* initDyArr(int capacity);
void insertDyArr(struct DynamicArr* arr, void* arrElent, int size);
void showDyArr(struct DynamicArr* arr, void(*pFunc)(void*));
void deleposDyArr(struct DynamicArr* arr, int index);
void delevalueDyArr(struct DynamicArr* arr, void* value, int(*valueP)(void*, void*));
void destroyDyArr(struct DynamicArr* arr);
void test01()
{
struct DynamicArr* arr = initDyArr(5);
printf("容量:%d\n", arr->m_capacity);
printf("大小:%d\n", arr->m_size);
int a = 6;
int b = 5;
int c = 4;
int d = 3;
int e = 2;
int f = 1;
insertDyArr(arr, &a, 0);
insertDyArr(arr, &b, 0);
insertDyArr(arr, &c, 2);
insertDyArr(arr, &d, 3);
insertDyArr(arr, &e, 4);
insertDyArr(arr, &f, 0);
printf("容量:%d\n", arr->m_capacity);
printf("大小:%d\n", arr->m_size);
showDyArr(arr, func);
int temp = 1;
delevalueDyArr(arr, &temp, deleteValue);
printf("删除后:\n");
printf("容量:%d\n", arr->m_capacity);
printf("大小:%d\n", arr->m_size);
showDyArr(arr, func);
printf("销毁后:\n");
destroyDyArr(arr);
showDyArr(arr, func);
}
int main()
{
test01();
return 0;
}
struct DynamicArr* initDyArr(int capacity)
{
if (capacity <= 0)
return NULL;
struct DynamicArr* arr = (struct DynamicArr*)malloc(sizeof(struct DynamicArr));
if (arr == NULL)
return NULL;
arr->pArr = (void**)malloc(sizeof(void*) * capacity);
arr->m_capacity = capacity;
arr->m_size = 0;
return arr;
}
void insertDyArr(struct DynamicArr* arr, void* arrElent, int size)
{
if (arr == NULL || size < 0)
return;
int tempSize = arr->m_size;
if (size > arr->m_capacity || arr->m_size == arr->m_capacity)
{
int newCapacity = arr->m_capacity * 2;
void** newPrr = malloc(sizeof(void*) * newCapacity);
for (int i = 0; i < arr->m_capacity; i++)
{
newPrr[i] = arr->pArr[i];
}
free(arr->pArr);
arr->pArr = newPrr;
arr->m_capacity = newCapacity;
}
if (size >= arr->m_size)
{
arr->pArr[arr->m_size] = arrElent;
arr->m_size++;
return;
}
tempSize = arr->m_size;
while (1)
{
if (arr->m_size == size)
{
arr->pArr[size] = arrElent;
arr->m_size = tempSize + 1;
break;
}
arr->pArr[arr->m_size] = arr->pArr[arr->m_size - 1];
arr->m_size--;
}
return;
}
void func(void* a)
{
int* tempInt = a;
printf("%d\n", *tempInt);
}
void showDyArr(struct DynamicArr* arr, void(*pFunc)(void*))
{
if (arr == NULL)
return;
for (int i = 0; i < arr->m_size; ++i)
{
pFunc(arr->pArr[i]);
}
}
void deleposDyArr(struct DynamicArr* arr, int index)
{
if (arr == NULL)
return;
for (int i = index - 1; i < arr->m_size - 1; ++i)
{
arr->pArr[i] = arr->pArr[i + 1];
}
arr->m_size--;
}
int deleteValue(void* a1, void* a2)
{
int* a = a1;
int* b = a2;
if (*a == *b)
return 1;
else
return 0;
}
void delevalueDyArr(struct DynamicArr* arr, void* value, int(*valueP)(void*, void*))
{
if (arr == NULL)
return;
for (int i = 0; i < arr->m_size; ++i)
{
if (valueP(arr->pArr[i], value))
{
for (int j = i; j < arr->m_size; j++)
{
arr->pArr[j] = arr->pArr[j + 1];
}
break;
}
}
arr->m_size--;
}
void destroyDyArr(struct DynamicArr* arr)
{
if (arr == NULL)
return;
if (arr->pArr != NULL)
{
free(arr->pArr);
arr->pArr = NULL;
}
free(arr);
arr = NULL;
}
2.1线性表的链式存储(单向链表)
前面我们写的线性表的顺序存储(动态数组)的案例,最大的缺点是插入和删除时
需要移动大量元素,这可以通过链表来解决。
链表为了表示每个数据元素与其直接后继元素之间的逻辑关系,每个元素除了
存储本身的信息外,还需要存储指示其直接后继的信息。
2.2单链表
线性表的链式存储结构中,每个节点中只包含一个指针域,这样的链表叫单链表。
通过每个节点的指针域将线性表的数据元素按其逻辑次序链接在一起。
2.3优点和缺点
优点:
无需一次性定制链表的容量
插入和删除操作无需移动数据元素
缺点:
数据元素必须保存后继元素的位置信息
获取指定数据的元素操作需要顺序访问之前的元素
2.4线性表的链式存储(单链表实现)
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct Person
{
char name[64];
int age;
};
struct LinkList
{
void* m_data;
struct LinkList* next;
int m_linkNum;
};
struct LinkList* init_Linklist()
{
struct LinkList* list = malloc(sizeof(struct LinkList));
if (list == NULL)
return NULL;
list->next = NULL;
list->m_linkNum = 0;
return list;
}
void insert_Linklist(struct LinkList* list,void* value,int pos)
{
if (list == NULL)
return;
if (value == NULL)
return;
if (pos < 0 || pos > list->m_linkNum)
pos = list->m_linkNum;
struct LinkList* temp1_insert = list;
for (int i = 0; i < pos; i++)
{
temp1_insert = temp1_insert->next;
}
struct LinkList* temp2_insert = malloc(sizeof(struct LinkList));
temp2_insert->m_data = value;
temp2_insert->next = NULL;
temp2_insert->next = temp1_insert->next;
temp1_insert->next = temp2_insert;
list->m_linkNum++;
}
void printStruct(void* temp)
{
struct Person* p1 = temp;
printf("姓名:%s,年龄:%d\n", p1->name, p1->age);
}
void find_Linklist(struct LinkList* list,void(*pPrint)(void*))
{
if (list == NULL)
return;
struct LinkList* temp = list;
printf("链表中元素个数为:%d\n", list->m_linkNum);
for (int i = 0; i < list->m_linkNum; i++)
{
temp = temp->next;
pPrint(temp->m_data);
}
}
void delete_indexLinklist(struct LinkList* list, int pos)
{
if (list == NULL || pos < 0 || pos > list->m_linkNum)
return;
struct LinkList* temp_del = list;
for (int i = 0; i < pos; i++)
{
temp_del = temp_del->next;
}
struct LinkList* temp2_del = malloc(sizeof(struct LinkList));
temp2_del = temp_del->next;
temp_del->next = temp2_del->next;
free(temp2_del);
list->m_linkNum--;
}
int myCompare(void* temp1,void* temp2)
{
struct Person* p1 = temp1;
struct Person* p2 = temp2;
return p1->age == p2->age && p1->name == p2->name;
}
void delete_valueLinklist(struct LinkList* list, void* value,int(*pCompare)(void*,void*))
{
if (list == NULL || value == NULL)
return;
struct LinkList* temp_del = list;
for (int i = 0; i < list->m_linkNum; i++)
{
temp_del = temp_del->next;
if (pCompare(temp_del->next->m_data, value))
{
break;
}
}
struct LinkList* temp2_del = malloc(sizeof(struct LinkList));
temp2_del = temp_del->next;
temp_del->next = temp2_del->next;
free(temp2_del);
list->m_linkNum--;
}
void clear_Linklist(struct LinkList* list)
{
if (list == NULL)
return;
struct LinkList* temp1 = list->next;
for (int i = 0; i < list->m_linkNum; i++)
{
struct LinkList* temp2 = temp1->next;
free(temp1);
temp1 = temp2;
}
list->next = NULL;
list->m_linkNum = 0;
}
void destroy_Linklist(struct LinkList* list)
{
if (list == NULL)
return;
clear_Linklist(list);
free(list);
list = NULL;
}
void test()
{
struct LinkList* m_List = init_Linklist();
struct Person p1 = { "张三",22 };
struct Person p2 = { "李四",23 };
struct Person p3 = { "王五",18 };
struct Person p4 = { "麻子",20 };
struct Person p5 = { "伙夫",19 };
insert_Linklist(m_List, &p1, 0);
insert_Linklist(m_List, &p2, 0);
insert_Linklist(m_List, &p3, 0);
insert_Linklist(m_List, &p4, 0);
insert_Linklist(m_List, &p5, 0);
printf("插入后链表内容为:\n");
find_Linklist(m_List, printStruct);
printf("删除后链表内容为:\n");
delete_valueLinklist(m_List, &p1, myCompare);
find_Linklist(m_List, printStruct);
clear_Linklist(m_List);
printf("清空后链表内容为:\n");
find_Linklist(m_List, printStruct);
destroy_Linklist(m_List);
}
int main()
{
test();
return 0;
}
下面附带另外一种写法:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct LinkNode
{
struct LinkNode* next;
};
struct LinkList
{
struct LinkNode n_head;
int n_size;
};
struct Person
{
struct LinkNode node;
char name[64];
int age;
};
struct LinkList* init_Linklist()
{
struct LinkList* mylist = malloc(sizeof(struct LinkList));
if (mylist == NULL)
return NULL;
mylist->n_head.next = NULL;
mylist->n_size = 0;
return mylist;
}
void insert_Linklist(struct LinkList* list,void* value,int pos)
{
if (list == NULL || value == NULL)
return;
if (pos < 0 || pos > list->n_size - 1 )
pos = list->n_size;
struct LinkList* m_list = list;
struct LinkNode* mValue = value;
struct LinkNode* pCurrent = &m_list->n_head;
for (int i = 0; i < pos; i++)
{
pCurrent = pCurrent->next;
}
mValue->next = pCurrent->next;
pCurrent->next = mValue;
m_list->n_size++;
}
void myPrint(void* temp)
{
struct Person* p = temp;
printf("姓名:%s,年龄:%d\n", p->name, p->age);
}
void find_Linklist(struct LinkList* list,void(*pPrint)(void*))
{
if (list == NULL)
return;
struct LinkList* m_list = list;
struct LinkNode* pCurrent = &m_list->n_head.next;
for (int i = 0; i < m_list->n_size; i++)
{
myPrint(pCurrent->next);
pCurrent = pCurrent->next;
}
}
void delete_Linklist(struct LinkList* list, int pos)
{
if (list == NULL)
return;
if (pos<0 || pos > list->n_size)
return;
struct LinkList* m_list = list;
struct LinkNode* pCurrent = &m_list->n_head.next;
for (int i = 0; i < pos; i++)
{
pCurrent = pCurrent->next;
}
struct LinkNode* pTemp = pCurrent->next;
pCurrent->next = pTemp->next;
m_list->n_size--;
}
void clear_Linklist(struct LinkList* list)
{
if (list == NULL)
return;
struct LinkList* m_list = list;
struct LinkNode* pCurrent = &m_list->n_head.next;
for (int i = 0; i < m_list->n_size; i++)
{
struct LinkList* m_Temp = pCurrent->next;
free(pCurrent);
pCurrent = m_Temp;
}
m_list->n_head.next = NULL;
m_list->n_size = 0;
}
void dextroy_Linklist(struct LinkList* list)
{
if (list == NULL)
return;
clear_Linklist(list);
free(list);
list = NULL;
}
void test()
{
struct LinkList* m_List = init_Linklist();
struct Person p1 = { NULL,"张三",22 };
struct Person p2 = { NULL,"李四",23 };
struct Person p3 = { NULL,"王五",18 };
struct Person p4 = { NULL,"麻子",20 };
struct Person p5 = { NULL,"伙夫",19 };
insert_Linklist(m_List, &p1, 3);
insert_Linklist(m_List, &p2, 0);
insert_Linklist(m_List, &p3, 0);
insert_Linklist(m_List, &p4, 0);
insert_Linklist(m_List, &p5, 0);
printf("插入后链表内容为:\n");
find_Linklist(m_List, myPrint);
printf("删除后链表内容为:\n");
delete_Linklist(m_List, 2);
find_Linklist(m_List, myPrint);
printf("清空后链表内容为:\n");
clear_Linklist(m_List);
find_Linklist(m_List, myPrint);
dextroy_Linklist(m_List);
}
int main()
{
test();
return 0;
}