通用链表
节点:
void* ptr; //数据域
指针域
运算:
常规功能+回调函数
#ifndef LIST_H
#define LIST_H
#include <stdbool.h>
#include <string.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* creat_list(void);
//头添加
void add_head_list(List* list,void* ptr);
//尾添加
void add_tail_list(List* list,void* ptr);
//插入
bool insert_list(List* list,size_t index,void*ptr);
//位置删除
bool del_index_list(List* list,size_t index);
//值删除
bool del_val_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_list(List* list);
//销毁
void destroy_list(List* list);
//遍历
void show_list(List* list,void (*show)(void*));
#endif//LIST_H
#include "list.h"
#include <stdlib.h>
//创建节点
static ListNode* creat_list_node(void* ptr)
{
ListNode* node=malloc(sizeof(ListNode));
node->ptr=ptr;
node->prev=node;
node->next=node;
return node;
}
//创建链表
List* creat_list(void)
{
List* list=malloc(sizeof(List));
list->head=creat_list_node(NULL);
list->size=0;
return list;
}
//在两个节点之间插入一个新节点
static void _add_list(ListNode* p,ListNode* n,void* ptr)
{
ListNode* node=creat_list_node(ptr);
p->next=node;
n->prev=node;
node->next=n;
node->prev=p;
}
//删除节点
static void _del_list(ListNode* node)
{
node->prev->next=node->next;
node->next->prev=node->prev;
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_list(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_val_list(List* list,void* ptr,int (*cmp)(const void*,const void*))
{
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;n!=list->head;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 false;
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* node=list->head->next;
while(node!=list->head)
{
ListNode* temp=node;
node=node->next;
free(temp->ptr);
free(temp);
}
list->size=0;
list->head->next=list->head;
list->head->prev=list->head;
}
//销毁
void destroy_list(List* list)
{
clear_list(list);
free(list->head);
free(list);
}
#include <stdio.h>
#include "list.h"
#include <stdlib.h>
#include <string.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=creat_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_tail_list(list,stu);
}
show_list(list,show_stu);
printf("====================\n");
Student s1={"hehe9"};
s1.id=1003;
del_val_list(list,&s1,cmp_id);
del_val_list(list,&s1,cmp_name);
show_list(list,show_stu);
s1.id=1006;
printf("query:");
show_stu(query_list(list,&s1,cmp_id));
}
数组与矩阵:
数组:存储空间连续、数据类型相同的表结构
矩阵:带二维信息的信息,一般使用二维数组存储矩阵
稀疏矩阵:矩阵中存储有效数据不多,绝大多数都是无效信息数据不需要存储,数量的多少没有特定的标准,全凭感觉
这些矩阵如果使用二维数组存储的话,会非常浪费军储存空间,为了节约内存,可以考虑对矩阵进行压缩处理。
特殊矩阵:
上三角矩阵:
[0][1][3][6]
[ ][2][4][7]
[ ][ ][5][8]
[ ][ ][ ][9]
压缩方法:用一维数组存储
数组的长度:n*(n+1)/2
对应关系:(j+1)*j/2+i ->对应一维数组对应的下标
行列的关系j>=i;
#include <stdio.h>
#include <stdlib.h>
int main(int argc,const char* argv[])
{
int n=0;
printf("请输入矩阵的阶数:");
scanf("%d",&n);
int arr[n][n];
int zip[n*(n+1)/2];
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(j>=i)
{
arr[i][j]=rand()%9+1;
zip[(j+1)*j/2+i]=arr[i][j];//压缩上三角矩阵
}
else
{
arr[i][j]=0;
}
printf("%d ",arr[i][j]);
}
printf("\n");
}
printf("-------------\n");
for(int i=0;i<n*(n+1)/2;i++)
{
printf("%d ",zip[i]);
}
}
下三角矩阵
[0][ ][ ][ ]
[1][2][ ][ ]
[3][4][5][ ]
[6][7][8][9]
压缩方法:用一维数组存储
数组的长度:n*(n+1)/2
对应关系:(i+1)*i/2+j ->对应一维数组对应的下标
行列的关系j<=i;
对称矩阵:沿(0,0)(1,1)(2,2)...(i,i)对称存储
[0] [1] [3] [6]
[1] [2] [4] [7]
[3] [4] [5] [8]
[6] [7] [8] [9]
压缩方法:用一维数组存储,把它当做上三角或者下三角看待即可
数组的长度:n*(n+1)/2
对应关系:(i+1)*i/2+j(下三角) 或者(j+1)*j/2+i(上三角)->对应一维数组对应的下标
行列的关系j<=i(下三角) 或者 j>=i(上三角);
对角矩阵(带状矩阵)
[0] [1] [ ] [ ]
[2] [3] [4] [ ]
[ ] [5] [6] [7]
[ ] [ ] [8] [9]
压缩方法:用一维数组存储
数组的长度:3n-2
对应关系:2*i+j->对应一维数组对应的下标
行列的关系abs(i-j)<=1
#include <stdio.h>
#include <stdlib.h>
int main(int argc,const char* argv[])
{
int n=0;
printf(">>>");
scanf("%d",&n);
int arr[n][n];
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(1>=abs(i-j))
{
arr[i][j]=i*2+j;
}
else
{
arr[i][j]=0;
}
printf("%2d ",arr[i][j]);
}
printf("\n");
}
}
无规律的稀疏矩阵:
采用三元组方式进行压缩
三元组
有三个数据项:行、列、值,构成一个整体,可以顺序存储也可以链式存储
#include <stdio.h>
#include <stdlib.h>
typedef struct Node
{
int row;
int col;
int val;
}Node;
typedef struct Triplet
{
Node* arr;
int cnt;//元素数量
int r_max;
int c_max;
}Triplet;
//构建三元组结构
Triplet* creat_triplet(int n,int m,int (*arr)[m],int cnt)
{
//创建三元组结构
Triplet* triplet=malloc(sizeof(Triplet));
triplet->arr=malloc(sizeof(Node)*cnt);
triplet->cnt=cnt;
triplet->r_max=n;
triplet->c_max=m;
//压缩矩阵
int index=0;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(arr[i][j])
{
triplet->arr[index].row=i;
triplet->arr[index].col=j;
triplet->arr[index++].val=arr[i][j];
}
}
}
return triplet;
}
void show_triplet(Triplet* triplet)
{
for(int i=0;i<triplet->cnt;i++)
{
printf("row:%d col:%d val:%d\n",
triplet->arr[i].row,triplet->arr[i].col,triplet->arr[i].val);
}
}
int main(int argc,const char* argv[])
{
int arr[8][9]={};
for(int i=0;i<10;i++)
{
int x=rand()%8;
int y=rand()%9;
arr[x][y]=rand()%100;
}
for(int i=0;i<8;i++)
{
for(int j=0;j<9;j++)
{
printf("%02d ",arr[i][j]);
}
printf("\n");
}
Triplet* triplet=creat_triplet(8,9,arr,10);
show_triplet(triplet);
}
注意:稀疏矩阵经过压缩后就丢失了随机访问的功能