第六天2017/04/11(2:Linux内核链表Demo、顺序表、链表的开发与设计)
生活随笔
收集整理的這篇文章主要介紹了
第六天2017/04/11(2:Linux内核链表Demo、顺序表、链表的开发与设计)
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
//結(jié)構(gòu)體相關(guān)的高級(jí)話題#include "stdio.h"
#include "stdlib.h"
#include "string.h"
//定義一個(gè)結(jié)構(gòu)體,就相當(dāng)于各個(gè)變量的偏移量也定下來(lái)了
struct student
{char name[32]; //32個(gè)字節(jié)int age; //4個(gè)字節(jié)char *na; //4個(gè)字節(jié)
};int main()
{struct student s = {"Mr.right" , 24 , "Victory"};struct student *p = &s;p = p+1;p = 0; //p = p - p; //此時(shí) p 相當(dāng)于 ((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地址空間進(jìn)行類型轉(zhuǎn)換,轉(zhuǎn)換為struct student *的結(jié)構(gòu)體指針;此處
//再指向結(jié)構(gòu)體中的age; 此處->是一個(gè)尋址操作,就是計(jì)算age的地址在哪里,沒(méi)有往age所指向的內(nèi)存空間讀寫數(shù)據(jù)//尋址操作對(duì)CPU來(lái)講,只不過(guò)是一個(gè)+-*/操作
//再取地址 ;
//在把地址轉(zhuǎn)換成十進(jìn)制 }
==================================================================================//【疑問(wèn)】為什么講上面的知識(shí):(int)&(((struct student *)0)->age)?
//【答】是為了引出“Linux內(nèi)核鏈表了解”!Linux內(nèi)核鏈表了解:
//不是鏈表包含業(yè)務(wù)結(jié)點(diǎn)
//而是業(yè)務(wù)結(jié)點(diǎn)包含鏈表//如何從鏈表結(jié)點(diǎn)的位置找到業(yè)務(wù)結(jié)點(diǎn)的位置呢?#define offsetof(TYPE,MEMBER) ((size_t)&((TYPE*)0)->MEMBER)
//求出MEMBER相對(duì)于TYPE結(jié)構(gòu)體的偏移量offset#define container_of(ptr,type,member) (type*)((char*)ptr - offsetof(type,member))
//求整個(gè)結(jié)構(gòu)體的偏移量
下圖是Linux內(nèi)核鏈表的示意圖:可以通過(guò)鏈表結(jié)點(diǎn),根據(jù)偏移量offset找到
業(yè)務(wù)結(jié)點(diǎn)的起始地址,對(duì)業(yè)務(wù)結(jié)點(diǎn)進(jìn)行操作。
============================================================================
上述圖簡(jiǎn)單介紹了公司的業(yè)務(wù)數(shù)據(jù)的設(shè)計(jì),代碼如下:
實(shí)現(xiàn):讓業(yè)務(wù)結(jié)點(diǎn)和鏈表結(jié)點(diǎn)進(jìn)行有效的分離
實(shí)質(zhì)上可以進(jìn)行“投機(jī)取巧,即永遠(yuǎn)把鏈表結(jié)點(diǎn)放在業(yè)務(wù)結(jié)點(diǎn)的第一個(gè)位置,此時(shí):鏈表結(jié)點(diǎn)相對(duì)于業(yè)務(wù)結(jié)點(diǎn)的偏移量offset為0.
struct List //鏈表結(jié)點(diǎn) {struct List *next; };struct student //業(yè)務(wù)結(jié)點(diǎn)(中有鏈表結(jié)點(diǎn)) {//鏈表結(jié)點(diǎn)struct List node;//數(shù)據(jù)元素int age;char name[100]; }; 【1、企業(yè)級(jí)財(cái)富庫(kù)線性表之單鏈表開發(fā)和設(shè)計(jì)】 //linklist.h函數(shù)聲明 #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函數(shù)實(shí)現(xiàn) #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) {//將業(yè)務(wù)結(jié)點(diǎn)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; //環(huán)境初始化for (i=0; (i<pos)&¤t->next!=NULL; i++ ) //尋找插入位置{current = current->next;} //插入新結(jié)點(diǎn)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;}//沒(méi)有初始化環(huán)境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測(cè)試程序 #include "linklist.h" #include <iostream> using namespace std;struct Student {LinkListNode node; //Linux內(nèi)核原理:業(yè)務(wù)結(jié)點(diǎn)中有鏈表結(jié)點(diǎn)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中的鏈表結(jié)點(diǎn)s1.node結(jié)點(diǎn)插入到鏈表listLinkList_Insert(list,&s2.node,0); //把s2中的鏈表結(jié)點(diǎn)s2.node結(jié)點(diǎn)插入到鏈表listLinkList_Insert(list,&s3.node,0); //把s3中的鏈表結(jié)點(diǎn)s3.node結(jié)點(diǎn)插入到鏈表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<<"刪除結(jié)點(diǎn)"<<endl;LinkList_Delete(list,1);print_LinkList(list);} /************************************************************************/ /************************************************************************/ 【2、企業(yè)級(jí)財(cái)富庫(kù)線性表之順序存儲(chǔ)開發(fā)和設(shè)計(jì)】 【核心問(wèn)題】業(yè)務(wù)數(shù)據(jù) 和 鏈表算法(底層庫(kù))是如何分離的? //seqlist.h:函數(shù)聲明 #ifndef __MY_SEQLIST_H__ #define __MY_SEQLIST_H__typedef void SeqList; typedef void SeqListNode;//疑問(wèn):為什么傳入的形參類型、返回的類型為void* ? //答:底層不想讓別人知道我是什么結(jié)構(gòu)的,也沒(méi)有必要讓別人知道SeqList* SeqList_Create(int capacity); //創(chuàng)建容量為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); //回調(diào)函數(shù)循環(huán)遍歷 #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:函數(shù)實(shí)現(xiàn) #include "seqlist.h" #include "stdlib.h" #include "stdio.h" #include "string.h"typedef struct _tag_SeqList {int capacity; //sizeof(數(shù)組),數(shù)組實(shí)際占有的內(nèi)存大小int length; //strlen(數(shù)組),數(shù)組中存放著幾個(gè)數(shù)據(jù)unsigned int *node ; //數(shù)組的頭指針 }TSeqList;//typdef的意思 把void 重新命名成SeqList/* void * SeqList_Create2(int capacity) //分配兩次內(nèi)存,惡心! {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) //創(chuàng)建一個(gè)長(zhǎng)度為capacity的數(shù)組,數(shù)組的數(shù)據(jù)類型是unsigned int {TSeqList *ret = NULL;if (capacity <= 0){return NULL;}ret = (TSeqList *)malloc(sizeof(TSeqList) + sizeof(unsigned int ) * capacity );//一次性全部分配內(nèi)存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) //不是釋放內(nèi)存,是直接把長(zhǎng)度設(shè)為0 {TSeqList *tlist = NULL;if (list == NULL){return ;}tlist = (TSeqList *)list;tlist->length = 0;//直接把長(zhǎng)度設(shè)為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; } //注解:實(shí)際位置和下標(biāo)位置總是相差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; //容錯(cuò) //插入位置length+1>=pos>=1if(pos > tlist->length+1){pos = tlist->length;}if(pos < 1){pos = 1;} //插入操作int i = tlist->length-1; //最后一個(gè)有效元素的位置while(i>=pos-1) //循環(huán)后移{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;} //緩存要?jiǎng)h除的結(jié)點(diǎn)ret = (SeqListNode*)tlist->node[pos-1]; //對(duì)鏈表元素值循環(huán)前移i = pos-1;while(i<=tlist->length-1){tlist->node[i] = tlist->node[i+1];i++;} //刪除后,長(zhǎng)度-1tlist->length --;return ret; }int for_each(void (*CALLBACK_print)(void*),void* list) {if(list == NULL)return -1;(*CALLBACK_print)(list);return 0; } =============================================================================== //線性表順序存儲(chǔ)測(cè)試.cpp:測(cè)試代碼 #include "seqlist.h" #include "stdlib.h" #include "stdio.h" #include "string.h"typedef struct _Teacher //業(yè)務(wù)結(jié)點(diǎn) {char name[64];int age ; }Teacher;void CALLBACK_print(void* list) //循環(huán)遍歷的回調(diào)函數(shù) {printf("循環(huán)遍歷:\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() { //創(chuàng)建業(yè)務(wù)數(shù)據(jù),并初始化Teacher t1 = {"Kobe",20};Teacher t2 = {"James",19};Teacher t3 = {"Curry",16}; //環(huán)境準(zhǔn)備int ret = 0, i = 0;SeqList* list = NULL; //創(chuàng)建線性表list = SeqList_Create(10);//仔細(xì)思考:業(yè)務(wù)數(shù)據(jù) 和 鏈表算法(底層庫(kù))是如何分離的。。。。。。//業(yè)務(wù)數(shù)據(jù)結(jié)點(diǎn)的管理(內(nèi)存的生命周期)甩給了上層應(yīng)用(業(yè)務(wù)模型) //插入ret = SeqList_Insert(list, (SeqListNode*)&t1, 1);ret = SeqList_Insert(list, (SeqListNode*)&t2, 1);ret = SeqList_Insert(list, (SeqListNode*)&t3, 1); //循環(huán)遍歷for_each(CALLBACK_print,list); //刪除 SeqList_Delete(list, 2);for_each(CALLBACK_print,list); //銷毀線性表SeqList_Destroy(list);system("pause"); }總結(jié)
以上是生活随笔為你收集整理的第六天2017/04/11(2:Linux内核链表Demo、顺序表、链表的开发与设计)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 第六天2017/04/11(1:结构体链
- 下一篇: 2、UNIX、Linux操作系统的发展历