我正在嘗試撰寫二進制決策樹。下面的代碼是作為整個演算法一部分的資料拆分的作業示例,盡管Valgrind 檢測到了一些錯誤。
您可能已經知道,樹是由節點組成的。在每個節點中,它通過分裂條件攜帶所有合格的觀察(行)。繼續,拆分也依賴于這些行。
并且可以通過貪婪搜索所有變數和值來找到最佳拆分條件,這意味著該資料拆分步驟可以執行數百次以找到最佳拆分(通過分類問題中的基尼指數評估)。我認為使用時可能會很昂貴memcpy。最糟糕的部分是我必須在每次拆分嘗試后為復制的行釋放記憶體。
所以,我在想是否有一種方法可以避免使用memcpy從字面上復制整個資料集,而是在每次拆分時只參考原始資料集的合格行。這樣,就沒有多余的memcpy和free需要的了。
問題:對于下面的示例,具體來說,如何使用一個指標來記錄合格行的地址,以便memcpy在執行貪婪搜索以進行最佳拆分時不需要并允許(簡單或方便地)訪問合格行。
如果您不清楚這個問題,請告訴我。非常感謝您的寶貴時間。
歡迎任何幫助和建議。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void printArray(double array[], unsigned int size) {
for (unsigned int i = 0; i < size; i) {
printf("%.3f ", array[i]);
}
printf("\n");
}
double **alloc_2dArray(unsigned int row, unsigned int col)
{
double **Array = (double **) malloc(row * sizeof(double *));
for (unsigned int i = 0; i < row; i ) {
Array[i] = (double *) malloc(col * sizeof(double));
}
return Array;
}
void dealloc_2dArray(double **Array, unsigned int row, unsigned int col)
{
for (unsigned int i = 0; i < row; i )
{
free(Array[i]);
}
free(Array);
}
int main(){
double **data = alloc_2dArray(4,4);
double delta[4] = {1,0,1,0};
double **dataL = alloc_2dArray(4,4);
double **dataR = alloc_2dArray(4,4);
int i,j;
int k=0;
//data initialization
for(i=0; i<4; i ){
for(j=0; j<4; j ){
data[i][j] = k ;
}
}
int l=0, r=0;
for(i=0; i<4; i ){
if((int)delta[i] ==0){
memcpy(dataL[l ], data[i], 4*sizeof(double));
}else{
memcpy(dataR[r ], data[i], 4*sizeof(double));
}
}
for(i = l; i<4; i ){
free(dataL[i]);
}
printf("l and r are %d %d\n", l, r);
dataL = realloc(dataL, l*sizeof(double*));
for(i = r; i<4; i ){
free(dataR[i]);
}
dataR = realloc(dataR, r*sizeof(double*));
for(i=0; i<4; i ){
if(dataL[i] != NULL){
printArray(dataL[i],4);
}
if(dataR[i] != NULL){
printArray(dataR[i],4);
}
}
dealloc_2dArray(data, 4,4);
dealloc_2dArray(dataL, l, 4);
dealloc_2dArray(dataR, r, 4);
return 0;
}
uj5u.com熱心網友回復:
我想你是在問你是否可以在分割矩陣中保留原始資料行指標。答案是肯定的,你可以。然而,所有權開始發揮作用。
對于下面的示例(沒有memcpy操作) ,指標床dataL和dataR指標床都是直接分配的,沒有分配給它們的實際資料行。這些行是從原始資料矩陣中“借來的”。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void printArray(double const array[], unsigned int size)
{
for (unsigned int i = 0; i < size; i)
{
printf("%-7.3f", array[i]);
}
printf("\n");
}
double **alloc_2dArray(unsigned int row, unsigned int col)
{
double **Array = malloc(row * sizeof(double *));
for (unsigned int i = 0; i < row; i )
{
Array[i] = (double *)malloc(col * sizeof(double));
}
return Array;
}
void dealloc_2dArray(double **Array, unsigned int row)
{
for (unsigned int i = 0; i < row; i )
{
free(Array[i]);
}
free(Array);
}
int main()
{
double **data = alloc_2dArray(4,4);
double delta[4] = {1, 0, 1, 0};
double **dataL = calloc(4, sizeof *dataL);
double **dataR = calloc(4, sizeof *dataR);
unsigned int i, j;
double k = 0;
// data initialization
for (i = 0; i < 4; i )
{
for (j = 0; j < 4; j )
{
data[i][j] = k;
k = 1;
}
}
printf("data[]\n");
for (i=0; i<4; i)
printArray(data[i], 4);
fputc('\n', stdout);
unsigned int l = 0, r = 0;
for (i = 0; i < 4; i )
{
if ((int)delta[i] == 0)
{
dataL[l ] = data[i];
}
else
{
dataR[r ] = data[i];
}
}
printf("l=%u r=%u\n", l, r);
dataL = realloc(dataL, l * sizeof(double *));
dataR = realloc(dataR, r * sizeof(double *));
printf("dataL[]\n");
for (i=0; i<l; i)
printArray(dataL[i], 4);
fputc('\n', stdout);
printf("dataR[]\n");
for (i=0; i<r; i)
printArray(dataR[i], 4);
fputc('\n', stdout);
free(dataL);
free(dataR);
dealloc_2dArray(data,4);
return 0;
}
輸出
data[]
0.000 1.000 2.000 3.000
4.000 5.000 6.000 7.000
8.000 9.000 10.000 11.000
12.000 13.000 14.000 15.000
l=2 r=2
dataL[]
4.000 5.000 6.000 7.000
12.000 13.000 14.000 15.000
dataR[]
0.000 1.000 2.000 3.000
8.000 9.000 10.000 11.000
關于這些行指標的實際所有權。只有你知道什么是合適的。如果原始data矩陣要繼續擁有它們,則必須注意確保data其行不會在使用時被破壞,dataL并且dataR仍在使用中。同樣,如果dataR并且dataL要獲得所有權,那么您不應該在釋放時釋放這些行data(但仍然釋放 的基指標床data),并且有dataL和dataRfree'ing 不僅要負責釋放它們的基指標床,還要釋放行為好。
無論如何,你去吧。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/461306.html
上一篇:如何在VGA記憶體中寫入換行符
