第六周day2

通用链表

    节点:

        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);
}

            注意:稀疏矩阵经过压缩后就丢失了随机访问的功能

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值