数据结构
Linux内核通用链表
- 既然链表中的节点不能包含万物,那么就让万物包含这个节点
通用链表
- 节点:
- void* ptr;// 数据域
- 指针域
- 运算:
- 常规功能 + 回调函数(函数指针那里讲过)
// 通用链表头文件
#ifndef LIST_H
#define LIST_H
#include <stdbool.h>
// 通用链表
typedef int (*Compar)(const void*,const void*);
// 链表节点
typedef struct ListNode
{
void* ptr;
struct ListNode* prev;
struct ListNode* next;
}ListNode;
// 通用链表结构
typedef struct List
{
ListNode* head;
size_t size;
}List;
// 创建链表
List* create_list(void);
// 头添加
void add_head_list(List* list,void* ptr);
// 尾添加
void add_tail_list(List* list,void* ptr);
// 插入
bool insert_index_lsit(List* list,size_t index,void* ptr);
// 按位置删除
bool del_index_list(List* list,size_t index);
// 按值删除
bool del_value_list(List* list,void* ptr,Compar cmp);
// 查询
void* query_list(List* list,void* ptr,Compar cmp);
// 访问
void* access_list(List* list,size_t index);
// 排序
void sort_list(List* list,Compar cmp);
// 清空
void clear_lsit(List* list);
// 销毁
void destroy(List* list);
// 遍历
void show_list(List* list,void (*show)(void*));
#endif//LIST_H
#include <stdlib.h>
#include "list.h"
// 创建节点
static ListNode* create_list_node(void* ptr)
{
ListNode* node = malloc(sizeof(ListNode));
node->ptr = ptr;
node->prev = node;
node->next = node;
return node;
}
// 创建链表
List* create_list(void)
{
List* list = malloc(sizeof(List));
list->head = create_list_node(NULL);
list->size = 0;
return list;
}
// 依赖函数
// 在两个节点之间插入一个新节点
static void _add_list(ListNode* p,ListNode* n,void* ptr)
{
ListNode* node = create_list_node(ptr);
p->next = node;
n->prev = node;
node->prev = p;
node->next = n;
}
// 删除节点
static void _del_list(ListNode* node)
{
node->next->prev = node->prev;
node->prev->next = node->next;
free(node->ptr);
free(node);
}
// 按位置访问节点
static ListNode* _index_list(List* list,size_t index)
{
if(index >= list->size) return NULL;
if(index < list->size/2)
{
ListNode* node = list->head->next;
while(index--) node = node->next;
return node;
}
else
{
ListNode* node = list->head->prev;
while(++index < list->size) node = node->prev;
return node;
}
}
// 头添加
void add_head_list(List* list,void* ptr)
{
_add_list(list->head,list->head->next,ptr);
list->size++;
}
// 尾添加
void add_tail_list(List* list,void* ptr)
{
_add_list(list->head->prev,list->head,ptr);
list->size++;
}
// 遍历
void show_list(List* list,void (*show)(void*))
{
for(ListNode* n=list->head->next; n!=list->head; n=n->next)
{
show(n->ptr);
}
}
// 插入
bool insert_index_lsit(List* list,size_t index,void* ptr)
{
ListNode* node = _index_list(list,index);
if(NULL == node) return false;
_add_list(node->prev,node,ptr);
list->size++;
return true;
}
// 按位置删除
bool del_index_list(List* list,size_t index)
{
ListNode* node = _index_list(list,index);
if(NULL == node) return false;
_del_list(node);
list->size--;
return true;
}
// 按值删除
bool del_value_list(List* list,void* ptr,Compar cmp)
{
for(ListNode* n=list->head->next; n!=list->head; n=n->next)
{
if(0 == cmp(ptr,n->ptr))
{
_del_list(n);
list->size--;
return true;
}
}
return false;
}
// 查询
void* query_list(List* list,void* ptr,Compar cmp)
{
for(ListNode* n=list->head->next; NULL!=n; n=n->next)
{
if(0 == cmp(ptr,n->ptr))
{
return n->ptr;
}
}
return NULL;
}
// 访问
void* access_list(List* list,size_t index)
{
ListNode* node = _index_list(list,index);
if(NULL == node) return NULL;
return node->ptr;
}
// 排序
void sort_list(List* list,Compar cmp)
{
for(ListNode* i=list->head->next; i->next!=list->head; i=i->next)
{
for(ListNode* j=i->next; j!=list->head; j=j->next)
{
if(1 == cmp(i->ptr,j->ptr))
{
void* temp = i->ptr;
i->ptr = j->ptr;
j->ptr = temp;
}
}
}
}
// 清空
void clear_list(List* list)
{
ListNode* n= list->head->next;
while(n!=list->head)
{
ListNode* temp = n;
n = n->next;
free(temp->ptr);
free(temp);
}
list->head->next = list->head;
list->head->prev = list->head;
list->size = 0;
}
// 销毁
void destroy_list(List* list)
{
clear_list(list);
free(list->head);
free(list);
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "list.h"
typedef struct Student
{
char name[20];
char sex;
int id;
}Student;
void show_stu(void* ptr)
{
Student* stu = ptr;
printf("姓名:%s 性别:%c 学号:%d\n",stu->name,stu->sex,stu->id);
}
int cmp_id(const void* p1,const void* p2)
{
const Student* s1 = p1,*s2 = p2;
if(s1->id == s2->id) return 0;
if(s1->id > s2->id) return 1;
return -1;
}
int cmp_name(const void* p1,const void* p2)
{
const Student* s1 = p1,*s2 = p2;
return strcmp(s1->name,s2->name);
}
int main(int argc,const char* argv[])
{
List* list = create_list();
for(int i=0; i<10; i++)
{
Student* stu = malloc(sizeof(Student));
sprintf(stu->name,"hehe%d",i);
stu->sex = i%2?'w':'m';
stu->id = 1000+i;
add_head_list(list,stu);
}
show_list(list,show_stu);
printf("-------------------------\n");
Student s1 = {"hehe1",'w',1000};
//del_value_list(list,&s1,cmp_id);
//del_value_list(list,&s1,cmp_name);
//show_list(list,show_stu);
printf("query: ");
show_stu(query_list(list,&s1,cmp_id));
Student* s2 = query_list(list,&s1,cmp_id);
s2->id = 8888;
show_list(list,show_stu);
destroy_list(list);
}
数组与矩阵
-
数组:存储空间连续、数据类型相同的表结构
-
矩阵:带二维信息的数据,一般使用二维数组来存储矩阵
- 稀疏矩阵:矩阵存储有效数据不多,绝大多数都是无效信息数据不需要存储(数量的多少没有特定的标准,全凭感觉)
- 这些矩阵如果使用二维数组存储的话,会非常浪费存储空间,为了节约内存,可以考虑对矩阵进行压缩
- 特殊矩阵:
- 上三角矩阵
- 压缩方法:用一维数组存储
- 数组的长度:n*(n+1)/2
- 对应关系:( j + 1 )* j / 2 + i ->对应的一维数组下标
- 行列的关系:j >= i
- 下三角矩阵
- 压缩方法:用一维数组存储
- 数组的长度:n*(n+1)/2
- 对应关系:( i + 1 )* i / 2 + j ->对应的一维数组下标
- 行列的关系:j <= i
- 对称矩阵:沿着主对角线对称
- 压缩方法:用一维数组存储,把它当作上三角或者下三角看待即可
- 数组的长度:n*(n+1)/2
- 对应关系:( j + 1 )* j / 2 + i 或者 ( i + 1 )* i / 2 + j ->对应的一维数组下标
- 行列的关系:j >= i 或 j <= i
- 对角矩阵(带状矩阵)
- 【0】【1】【 】【 】
- 【2】【3】【4】【 】
- 【 】【5】【6】【7】
- 【 】【 】【8】【9】
- 压缩方法:用一维数组存储
- 数组的长度:3n-2
- 对应关系:2*i + j
- 行列的关系:abs(i-j) <= 1
- 上三角矩阵
- 无规律的稀疏矩阵:
- 采用三元组方式进行压缩
- 三元组:
- 有三个数据项:行、列、值,构成一个整体,可以顺序存储,也可以链式存储
- 注意:稀疏矩阵经过压缩后就丢失了随机访问的功能