第六天2017/04/11(2:Linux内核链表Demo、顺序表、链表的开发与设计)
生活随笔
收集整理的这篇文章主要介绍了
第六天2017/04/11(2:Linux内核链表Demo、顺序表、链表的开发与设计)
小编觉得挺不错的,现在分享给大家,帮大家做个参考.
//结构体相关的高级话题#include "stdio.h"
#include "stdlib.h"
#include "string.h"
//定义一个结构体,就相当于各个变量的偏移量也定下来了
struct student
{char name[32]; //32个字节int age; //4个字节char *na; //4个字节
};int main()
{struct student s = {"Mr.right" , 24 , "Victory"};struct student *p = &s;p = p+1;p = 0; //p = p - p; //此时 p 相当于 ((struct student *)0)int i = (int )(&(p->name)); //0 int i = (int)(&(((struct student *)0)->name))int j = (int )(&(p->age)); //32 int j = (int)(&(((struct student *)0)->age))int k = (int )(&(p->na)); //36 int k = (int)(&(((struct student *)0)->na))int m = (int)&(((struct student *)0)->name);//把0地址空间进行类型转换,转换为struct student *的结构体指针;此处
//再指向结构体中的age; 此处->是一个寻址操作,就是计算age的地址在哪里,没有往age所指向的内存空间读写数据//寻址操作对CPU来讲,只不过是一个+-*/操作
//再取地址 ;
//在把地址转换成十进制 }
==================================================================================//【疑问】为什么讲上面的知识:(int)&(((struct student *)0)->age)?
//【答】是为了引出“Linux内核链表了解”!Linux内核链表了解:
//不是链表包含业务结点
//而是业务结点包含链表//如何从链表结点的位置找到业务结点的位置呢?#define offsetof(TYPE,MEMBER) ((size_t)&((TYPE*)0)->MEMBER)
//求出MEMBER相对于TYPE结构体的偏移量offset#define container_of(ptr,type,member) (type*)((char*)ptr - offsetof(type,member))
//求整个结构体的偏移量
下图是Linux内核链表的示意图:可以通过链表结点,根据偏移量offset找到
业务结点的起始地址,对业务结点进行操作。
============================================================================
上述图简单介绍了公司的业务数据的设计,代码如下:
实现:让业务结点和链表结点进行有效的分离
实质上可以进行“投机取巧,即永远把链表结点放在业务结点的第一个位置,此时:链表结点相对于业务结点的偏移量offset为0.
struct List //链表结点 {struct List *next; };struct student //业务结点(中有链表结点) {//链表结点struct List node;//数据元素int age;char name[100]; }; 【1、企业级财富库线性表之单链表开发和设计】 //linklist.h函数声明 #ifndef _MYLINKLIST_H_ #define _MYLINKLIST_H_typedef void LinkList;typedef struct _tag_LinkListNode {struct _tag_LinkListNode* next; }LinkListNode;LinkList* LinkList_Create(); void LinkList_Destroy(LinkList* list); void LinkList_Clear(LinkList* list); int LinkList_Length(LinkList* list); int LinkList_Insert(LinkList* list, LinkListNode* node, int pos); LinkListNode* LinkList_Get(LinkList* list, int pos); LinkListNode* LinkList_Delete(LinkList* list, int pos); #endif ========================================================================= //linklist.cpp函数实现 #include "stdlib.h" #include "stdio.h" #include "string.h"#include "linklist.h"typedef struct _tag_LinkList {LinkListNode header;int length; }TLinkList;LinkList* LinkList_Create() {TLinkList *tList = (TLinkList *)malloc(sizeof(TLinkList));if (tList == NULL){return NULL;}tList->header.next = NULL;tList->length = 0;return tList; }void LinkList_Destroy(LinkList* list) {if (list != NULL){free(list);}return ; }void LinkList_Clear(LinkList* list) {TLinkList *tList = (TLinkList *)list;if (tList == NULL){return ;}tList->length = 0;tList->header.next = NULL;return ; }int LinkList_Length(LinkList* list) {TLinkList *tList = (TLinkList *)list;if (tList == NULL){return -1;}return tList->length; }int LinkList_Insert(LinkList* list, LinkListNode* pNew, int pos) {//将业务结点s中的s.node元素插入到单链表中int i = 0;TLinkList *tList = (TLinkList *)list;LinkListNode *current = NULL;if (tList == NULL || pNew == NULL || pos<0){return -1;}current = &tList->header; //环境初始化for (i=0; (i<pos)&¤t->next!=NULL; i++ ) //寻找插入位置{current = current->next;} //插入新结点pNewpNew->next = current->next;current->next = pNew;tList->length ++;return 0; }LinkListNode* LinkList_Get(LinkList* list, int pos) {int i = 0;TLinkList *tList = (TLinkList *)list;LinkListNode *current = NULL;LinkListNode *ret = NULL;if (list==NULL || pos<0 || pos>=tList->length){return NULL;}current = &tList->header;for (i=0; i<pos; i++){current = current->next;}ret = current->next;return ret; }LinkListNode* LinkList_Delete(LinkList* list, int pos) {int i = 0;TLinkList *tList = (TLinkList *)list;LinkListNode *current = NULL;LinkListNode *ret = NULL;if (list==NULL || pos<0 || pos>=tList->length){return NULL;}//没有初始化环境current = &tList->header;for (i=0; i<pos; i++){current = current->next;}ret = current->next;current->next = ret->next;tList->length --;return ret; } ========================================================================= //main.cpp测试程序 #include "linklist.h" #include <iostream> using namespace std;struct Student {LinkListNode node; //Linux内核原理:业务结点中有链表结点char name[100];int age; };void print_LinkList(void* list) //遍历打印链表 {for (int i=0; i<LinkList_Length(list); i++){struct Student *tmp = (struct Student*)LinkList_Get(list, i);printf("name: %s , age: %d\n", tmp->name,tmp->age);} }int main() {Student s1; strcpy(s1.name,"Tom"); s1.age = 20;Student s2; strcpy(s2.name,"Tim"); s2.age = 21;Student s3; strcpy(s3.name,"Kim"); s3.age = 22;LinkList* list = list = LinkList_Create(); /************************************************************************/ //case1:LinkList_Insert(list,&s1.node,0); //把s1中的链表结点s1.node结点插入到链表listLinkList_Insert(list,&s2.node,0); //把s2中的链表结点s2.node结点插入到链表listLinkList_Insert(list,&s3.node,0); //把s3中的链表结点s3.node结点插入到链表list//LinkList_Insert(list,(LinkListNode*)(&s1.node),0);//LinkList_Insert(list,(LinkListNode*)(&s2.node),0);//LinkList_Insert(list,(LinkListNode*)(&s3.node),0); //case2://LinkList_Insert(list,(LinkListNode*)(&s1),0);//LinkList_Insert(list,(LinkListNode*)(&s2),0);//LinkList_Insert(list,(LinkListNode*)(&s3),0);print_LinkList(list); /************************************************************************/cout<<"删除结点"<<endl;LinkList_Delete(list,1);print_LinkList(list);} /************************************************************************/ /************************************************************************/ 【2、企业级财富库线性表之顺序存储开发和设计】 【核心问题】业务数据 和 链表算法(底层库)是如何分离的? //seqlist.h:函数声明 #ifndef __MY_SEQLIST_H__ #define __MY_SEQLIST_H__typedef void SeqList; typedef void SeqListNode;//疑问:为什么传入的形参类型、返回的类型为void* ? //答:底层不想让别人知道我是什么结构的,也没有必要让别人知道SeqList* SeqList_Create(int capacity); //创建容量为capacity的顺序线性表 void SeqList_Destroy(SeqList* list); //释放线性表list void SeqList_Clear(SeqList* list); //清空线性表list int SeqList_Length(SeqList* list); int SeqList_Capacity(SeqList* list); int SeqList_Insert(SeqList* list, SeqListNode* node, int pos); SeqListNode* SeqList_Get(SeqList* list, int pos); SeqListNode* SeqList_Delete(SeqList* list, int pos); int for_each(void (*CALLBACK_print)(void*),void* list); //回调函数循环遍历 #endif //void* SeqList_Create(int capacity); //void SeqList_Destroy(void* list); //void SeqList_Clear(void* list); //int SeqList_Length(void* list); //int SeqList_Capacity(void* list); //int SeqList_Insert(void* list, void* node, int pos); //void* SeqList_Get(void* list, int pos); //void* SeqList_Delete(void* list, int pos);=============================================================================== //seqlist.cpp:函数实现 #include "seqlist.h" #include "stdlib.h" #include "stdio.h" #include "string.h"typedef struct _tag_SeqList {int capacity; //sizeof(数组),数组实际占有的内存大小int length; //strlen(数组),数组中存放着几个数据unsigned int *node ; //数组的头指针 }TSeqList;//typdef的意思 把void 重新命名成SeqList/* void * SeqList_Create2(int capacity) //分配两次内存,恶心! {TSeqList *ret = NULL;ret = (TSeqList *)malloc(sizeof(TSeqList));if (ret == NULL){return NULL;}ret->capacity = capacity;ret->node = (unsigned int *)malloc(sizeof(unsigned int ) * capacity);if (ret->node == NULL){return NULL;}ret->length = 0;return ret; } */void * SeqList_Create(int capacity) //创建一个长度为capacity的数组,数组的数据类型是unsigned int {TSeqList *ret = NULL;if (capacity <= 0){return NULL;}ret = (TSeqList *)malloc(sizeof(TSeqList) + sizeof(unsigned int ) * capacity );//一次性全部分配内存if (ret == NULL){return NULL;}ret->capacity = capacity; ret->length = 0;ret->node = (unsigned int *)(ret + 1);return ret; }void SeqList_Destroy(SeqList* list) {if (list == NULL){return ;}free(list);return ; }void SeqList_Clear(SeqList* list) //不是释放内存,是直接把长度设为0 {TSeqList *tlist = NULL;if (list == NULL){return ;}tlist = (TSeqList *)list;tlist->length = 0;//直接把长度设为0return ; }int SeqList_Length(SeqList* list) {TSeqList *tlist = (TSeqList *)list;if (list == NULL){return -1;}return tlist->length; }int SeqList_Capacity(SeqList* list) {TSeqList *tlist = (TSeqList *)list;if (list == NULL){return -1;}return tlist->capacity; } //注解:实际位置和下标位置总是相差1 int SeqList_Insert(SeqList* list, SeqListNode* node, int pos) //插入位置:length+1>=pos>=1 {if(list == NULL||node == NULL)return -1;TSeqList *tlist = (TSeqList*)list; //capacity空间不够if(tlist->length >= tlist->capacity) return -2; //容错 //插入位置length+1>=pos>=1if(pos > tlist->length+1){pos = tlist->length;}if(pos < 1){pos = 1;} //插入操作int i = tlist->length-1; //最后一个有效元素的位置while(i>=pos-1) //循环后移{tlist->node[i+1] = tlist->node[i];i--;}tlist->node[pos-1] = (unsigned int)node; //插入tlist->length++;return 0; }SeqListNode* SeqList_Get(SeqList* list, int pos) //查找位置:length>=pos>=1 {TSeqList *tlist = (TSeqList *)list;if (list== NULL || pos<1 || pos>tlist->length){return NULL;}return (SeqListNode*)tlist->node[pos-1]; }SeqListNode* SeqList_Delete(SeqList* list, int pos) //删除位置:length>=pos>=1 {int i = 0;TSeqList *tlist = (TSeqList *)list;SeqListNode* ret = NULL;if (list == NULL || pos<1 || pos>tlist->length){return NULL;} //缓存要删除的结点ret = (SeqListNode*)tlist->node[pos-1]; //对链表元素值循环前移i = pos-1;while(i<=tlist->length-1){tlist->node[i] = tlist->node[i+1];i++;} //删除后,长度-1tlist->length --;return ret; }int for_each(void (*CALLBACK_print)(void*),void* list) {if(list == NULL)return -1;(*CALLBACK_print)(list);return 0; } =============================================================================== //线性表顺序存储测试.cpp:测试代码 #include "seqlist.h" #include "stdlib.h" #include "stdio.h" #include "string.h"typedef struct _Teacher //业务结点 {char name[64];int age ; }Teacher;void CALLBACK_print(void* list) //循环遍历的回调函数 {printf("循环遍历:\n");for (int i=1; i<=SeqList_Length(list); i++){Teacher *tmp = (Teacher *)SeqList_Get(list, i);printf("name:%s , age:%d \n", tmp->name,tmp->age);} }void main() { //创建业务数据,并初始化Teacher t1 = {"Kobe",20};Teacher t2 = {"James",19};Teacher t3 = {"Curry",16}; //环境准备int ret = 0, i = 0;SeqList* list = NULL; //创建线性表list = SeqList_Create(10);//仔细思考:业务数据 和 链表算法(底层库)是如何分离的。。。。。。//业务数据结点的管理(内存的生命周期)甩给了上层应用(业务模型) //插入ret = SeqList_Insert(list, (SeqListNode*)&t1, 1);ret = SeqList_Insert(list, (SeqListNode*)&t2, 1);ret = SeqList_Insert(list, (SeqListNode*)&t3, 1); //循环遍历for_each(CALLBACK_print,list); //删除 SeqList_Delete(list, 2);for_each(CALLBACK_print,list); //销毁线性表SeqList_Destroy(list);system("pause"); }总结
以上是生活随笔为你收集整理的第六天2017/04/11(2:Linux内核链表Demo、顺序表、链表的开发与设计)的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: 第六天2017/04/11(1:结构体链
- 下一篇: 2、UNIX、Linux操作系统的发展历