第六天2017/04/11(2:Linux内核链表Demo、顺序表、链表的开发与设计)
生活随笔
收集整理的這篇文章主要介紹了
第六天2017/04/11(2:Linux内核链表Demo、顺序表、链表的开发与设计)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
//結構體相關的高級話題#include "stdio.h"
#include "stdlib.h"
#include "string.h"
//定義一個結構體,就相當于各個變量的偏移量也定下來了
struct student
{char name[32]; //32個字節(jié)int age; //4個字節(jié)char *na; //4個字節(jié)
};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所指向的內存空間讀寫數(shù)據(jù)//尋址操作對CPU來講,只不過是一個+-*/操作
//再取地址 ;
//在把地址轉換成十進制 }
==================================================================================//【疑問】為什么講上面的知識:(int)&(((struct student *)0)->age)?
//【答】是為了引出“Linux內核鏈表了解”!Linux內核鏈表了解:
//不是鏈表包含業(yè)務結點
//而是業(yè)務結點包含鏈表//如何從鏈表結點的位置找到業(yè)務結點的位置呢?#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內核鏈表的示意圖:可以通過鏈表結點,根據(jù)偏移量offset找到
業(yè)務結點的起始地址,對業(yè)務結點進行操作。
============================================================================
上述圖簡單介紹了公司的業(yè)務數(shù)據(jù)的設計,代碼如下:
實現(xiàn):讓業(yè)務結點和鏈表結點進行有效的分離
實質上可以進行“投機取巧,即永遠把鏈表結點放在業(yè)務結點的第一個位置,此時:鏈表結點相對于業(yè)務結點的偏移量offset為0.
struct List //鏈表結點 {struct List *next; };struct student //業(yè)務結點(中有鏈表結點) {//鏈表結點struct List node;//數(shù)據(jù)元素int age;char name[100]; }; 【1、企業(yè)級財富庫線性表之單鏈表開發(fā)和設計】 //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ù)實現(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è)務結點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;} //插入新結點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;}//沒有初始化環(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測試程序 #include "linklist.h" #include <iostream> using namespace std;struct Student {LinkListNode node; //Linux內核原理:業(yè)務結點中有鏈表結點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、企業(yè)級財富庫線性表之順序存儲開發(fā)和設計】 【核心問題】業(yè)務數(shù)據(jù) 和 鏈表算法(底層庫)是如何分離的? //seqlist.h:函數(shù)聲明 #ifndef __MY_SEQLIST_H__ #define __MY_SEQLIST_H__typedef void SeqList; typedef void SeqListNode;//疑問:為什么傳入的形參類型、返回的類型為void* ? //答:底層不想讓別人知道我是什么結構的,也沒有必要讓別人知道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); //回調函數(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ù)實現(xiàn) #include "seqlist.h" #include "stdlib.h" #include "stdio.h" #include "string.h"typedef struct _tag_SeqList {int capacity; //sizeof(數(shù)組),數(shù)組實際占有的內存大小int length; //strlen(數(shù)組),數(shù)組中存放著幾個數(shù)據(jù)unsigned int *node ; //數(shù)組的頭指針 }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) //創(chuà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 );//一次性全部分配內存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) //循環(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;} //緩存要刪除的結點ret = (SeqListNode*)tlist->node[pos-1]; //對鏈表元素值循環(huán)前移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 //業(yè)務結點 {char name[64];int age ; }Teacher;void CALLBACK_print(void* list) //循環(huán)遍歷的回調函數(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è)務數(shù)據(jù),并初始化Teacher t1 = {"Kobe",20};Teacher t2 = {"James",19};Teacher t3 = {"Curry",16}; //環(huán)境準備int ret = 0, i = 0;SeqList* list = NULL; //創(chuàng)建線性表list = SeqList_Create(10);//仔細思考:業(yè)務數(shù)據(jù) 和 鏈表算法(底層庫)是如何分離的。。。。。。//業(yè)務數(shù)據(jù)結點的管理(內存的生命周期)甩給了上層應用(業(yè)務模型) //插入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"); }總結
以上是生活随笔為你收集整理的第六天2017/04/11(2:Linux内核链表Demo、顺序表、链表的开发与设计)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 第六天2017/04/11(1:结构体链
- 下一篇: 第七天2017/04/14(C++对C的