實驗五 內存管理實驗

實驗五? 內存管理實驗

一、實驗目的

1、了解操作系統動態分區存儲管理過程和方法。

2、掌握動態分區存儲管理的主要數據結構--空閑表區。

3、加深理解動態分區存儲管理中內存的分配和回收。

4、掌握空閑區表中空閑區3種不同放置策略的基本思想和實現過程。

5、通過模擬程序實現動態分區存儲管理。

6、了解請求分頁虛擬存儲管理技術的方法和特點。

7、通過模擬實現請求頁式存儲管理的幾種基本頁面置換算法。

8、掌握頁面置換算法種缺頁率、置換率和命中率的計算方法。

、實驗內容

1、編程模擬實現動態分區管理中內存的分配和回收及空閑區表的管理。(2分)

首次適應算法(First Fit)參考程序:

#include<unistd.h>

#include<stdio.h>

#include<stdlib.h>

#define N 5

struct freearea

{

??? int startaddr;? //空閑區起始地址

??? int size;????? //空閑區大小

??? int state;???? //1表示空閑,0表示占用

}freeblock[N]={{20,20,1},{80,50,1},{150,100,1},{300,30,1},{600,100,1}};

int alloc(int size)

{

??? int i,tag=0,allocaddr;

??? for(i=0;i<N;i++)

??? {

??????? if(freeblock[i].state==1 && freeblock[i].size>size) //申請空間小于空閑空間

??????? {

?????????? allocaddr=freeblock[i].startaddr;?? //作業地址

?????????? freeblock[i].startaddr+=size;?? //新空閑區起始地址

?????????? freeblock[i].size-=size;?????? //新空閑區大小

?????????? tag=1;? //分配標記

?????????? break;

??????? }

??????? else if(freeblock[i].state==1 && freeblock[i].size==size)//申請空間正好等于空閑空間

??????? {

?????????? allocaddr=freeblock[i].startaddr;

?????????? freeblock[i].state=0;tag=1;

?????????? break;

??????? }

??? }

??? if(tag==0)? //表示沒找到合適的空閑區,未分配內存

??????? allocaddr=-1;

??? return allocaddr; //返回作業地址

}

void setfree(int addr,int size) //傳過來的參數是要釋放內存的起始地址和大小

{

??? int i,tag1=0,tag2=0,n1=0,n2=0;

??? for(i=0;i<N;i++)

??? {

??????? if(freeblock[i].startaddr+freeblock[i].size==addr && freeblock[i].state==1)

??????? {

?????????? tag1=1; ??? //有上鄰標記

?????????? n1=i;?? //記錄上鄰數組位置(分區號)

?????????? break;

??????? }

??? }

??? for(i=0;i<N;i++)

??? {

??????? if(freeblock[i].startaddr==addr+size && freeblock[i].state==1)?

??????? {

?????????? tag2=1;???? //有下鄰標記

?????????? n2=i;?? //記錄下鄰數組位置(分區號)

?????????? break;

??????? }

??? }??????

??? if(tag1==1 && tag2==0)? //有上鄰無下鄰

??? {

??????? freeblock[n1].size+=size;

??? }

??? else if(tag1==1 && tag2==1) //有上鄰有下鄰

??? {

?????????? freeblock[n1].size+=freeblock[n2].size+size;

?????????? freeblock[n2].state=0;//???

??? }

??? else if(tag1==0 && tag2==1) //無上鄰有下鄰

??? {

??????? freeblock[n2].startaddr=addr;

??????? freeblock[n2].size+=size;

??? }

??? else??? //無上鄰無下鄰(表明空間正好全部分配出去,空間的狀態為0)

??? {

??????? for(i=0;i<N;i++)

??????? {

?????????? if(freeblock[i].state==0)?? //通過空間狀態值找到這塊空間

?????????? {

?????????????? freeblock[i].startaddr=addr;

?????????????? freeblock[i].size=size;

?????????????? freeblock[i].state=1;

?????????????? break;

?????????? }

??????? }

??? }

}

void adjust()

{

??? int i,j;

??? struct freearea temp;

??? for(i=1;i<N;i++)??? //依據首次適應算法將空閑區按起始地址由低到高冒泡排序

??? {

??????? for(j=0;j<N-i;j++)

??????? {

?????????? if(freeblock[j].startaddr>freeblock[j+1].startaddr)

?????????? {

?????????????? temp=freeblock[j];

?????????????? freeblock[j]=freeblock[j+1];

?????????????? freeblock[j+1]=temp;

?????????? }

??????? }

??? }

??? for(i=1;i<N;i++)??? //把狀態為0的排到后面

??? {

??????? for(j=0;j<N-i;j++)

??????? {

?????????? if(freeblock[j].state==0 && freeblock[j+1].state==1)

?????????? {

?????????????? temp=freeblock[j];

?????????????? freeblock[j]=freeblock[j+1];

?????????????? freeblock[j+1]=temp;

?????????? }

??????? }

??? }

}

void print()

{

??? int i;

??? printf("\t|-------------------------------|\n");

??? printf("\t|startaddr??? size????? state |\n");

??? for(i=0;i<N;i++)

??? printf("\t|%4d???? %4d ? %4d |\n",freeblock[i].startaddr,freeblock[i].size,freeblock[i].state);???

}

int main()

{

??? int size,addr;

??? char c1,c2,c;

??? printf("At first the free memory is this:\n");//首先,空閑區是這樣的

??? adjust();

??? print();???

??? printf("Is there any job request memory?(y or n):");//有作業需要申請內存么?

??? while((c1=getchar())=='y')

??? {

??????? printf("Input request memory size:"); //輸入所需內存大小

??????? scanf("%d",&size);

??????? addr=alloc(size); //調用內存分配函數,返回的是作業的起始地址

??????? if(addr==-1)

?????????? printf("There is no fit memory.Please wait!!!\n");

??????? else

??????? {

?????????? printf("Job's memory start address is:%d\n",addr);??? //輸出作業的起始地址

?????????? printf("Job's size is:%d\n",size);? //輸出作業大小

?????????? printf("After allocation the free memory is this:\n");??? //分配后可用內存如下:???????? adjust();

?????????? print();

?????????? printf("Job is running.\n");

??????? }

??????? getchar();

??????? printf("Is there any memory for free?(y or n):");//有需要釋放的內存么?

??????? while((c2=getchar())=='y')

??????? {

?????????? printf("Input free area startaddress:");

?????????? scanf("%d",&addr);? //輸入要釋放內存的起始地址

?????????? printf("Input free area size:");

?????????? scanf("%d",&size);? //輸入要釋放內存的大小

?????????? setfree(addr,size); //調用釋放內存函數

?????????? adjust();

?????????? print();

?????????? getchar();

?????????? printf("Is there any memory for free?(y or n):");?? ???

??????? }

??????? getchar();

??????? printf("Is there any job request memory?(y or n):");

??? }

??? return 0;??

}

運行結果截屏(包含分配和回收兩部分):

分析該程序,列出各模塊實現的功能:

  1. alloc()

根據作業的大小申請空閑內存區域,并返回作業的起始地址。

2)setfree()

釋放指定起始地址和大小的內存區域,將其設置為空閑狀態。

3) adjust()

根據首次適應算法對空閑區進行排序和整理。

  1. 修改上題,用最佳適應算法和最壞適應算法模擬內存空間的分配和回收。(4分)

注:只需列出程序不同部分,無需將整個程序列出。

  1. 最佳適應算法

int best_fit_alloc(int size) {

??? int i, allocaddr = -1, min_size = INT_MAX;

??? for (i = 0; i < N; i++) {

??????? if (freeblock[i].state == 1 && freeblock[i].size >= size && freeblock[i].size < min_size) {

??????????? allocaddr = freeblock[i].startaddr;

??????????? min_size = freeblock[i].size;

??????? }

??? }

??? if (allocaddr != -1) {

??????? for (i = 0; i < N; i++) {

??????????? if (freeblock[i].startaddr == allocaddr) {

??????????????? if (freeblock[i].size > size) {

??????????????????? freeblock[i].startaddr += size;

??????????????????? freeblock[i].size -= size;

??????????????? } else {

??????????????????? freeblock[i].state = 0;

??????????????? }

??????????????? break;

??????????? }

??????? }

??? }

???

??? return allocaddr;

}

  1. 最壞適應算法

int worst_fit_alloc(int size) {

??? int i, allocaddr = -1, max_size = -1;

??? for (i = 0; i < N; i++) {

??????? if (freeblock[i].state == 1 && freeblock[i].size >= size && freeblock[i].size > max_size) {

??????????? allocaddr = freeblock[i].startaddr;

??????????? max_size = freeblock[i].size;

??????? }

??? }

??? if (allocaddr != -1) {

??????? for (i = 0; i < N; i++) {

??????????? if (freeblock[i].startaddr == allocaddr) {

??????????????? if (freeblock[i].size > size) {

??????????????????? freeblock[i].startaddr += size;

??????????????????? freeblock[i].size -= size;

??????????????? } else {

??????????????????? freeblock[i].state = 0;

??????????????? }

??????????????? break;

??????????? }

??????? }

??? }

???

??? return allocaddr;

}

  1. 編寫程序實現先進先出頁面置換算法,并計算缺頁次數,缺頁率,置換次數和命中率。(2分)

參考程序:

#include <stdio.h>

//初始化內存隊列

void initializeList(int list[],int number){

??? int i;

??? for (i = 0; i < number; i ++) {

??????? list[i] = -1;

??? }

}

//展示要訪問頁面號數組

void showList(int list[], int number){

??? int i;

??? for (i = 0; i < number; i ++) {

??????? printf("%2d",list[i]);

??? }

??? printf("\n");

}

//展示當前內存狀態

void showMemoryList(int list[],int phyBlockNum){

??? int i;

??? for (i = 0; i < phyBlockNum; i ++) {

??????? if (list[i] == -1) {

??????????? break;

??????? }

??????? printf(" |%d|",list[i]);

??? }

??? printf("\n");

}

//計算各項指標

void informationCount(int missingCount,int replaceCount,int pageNum){

??? printf("缺頁次數:%d?? 缺頁率:%d/%d\n",missingCount,missingCount,pageNum);

??? double result = (double)(pageNum - missingCount)/(double)pageNum;

??? printf("置換次數:%d? 命中率:%.2f\n",replaceCount,result);

}

//先進先出置換算法

void replacePageByFIFO(int memoryList[],int phyNum,int strList[],int pageNum){

??? //置換次數

??? int replaceCount = 0;

??? //缺頁次數

??? int missingCount = 0;

??? //記錄當前最早進入內存的下標

??? int pointer = 0;

??

//記錄當前頁面的訪問情況: 0 未訪問

int i,j,isVisited = 0;

??? for (i = 0; i < pageNum; i ++) {

??????? isVisited = 0;

??????? //判斷是否需要置換->內存已滿且需要訪問的頁面不在內存中

??????? for (j = 0; j < phyNum; j ++) {

??????????? if (memoryList[j] == strList[i]) {

??????????????? //該頁面已經存在內存中

??????????????? //修改訪問情況

??????????????? isVisited = 1;

??????????????? //展示

??????????????? printf("%d\n",strList[i]);

??????????????? break;

??????????? }

??????????? if (memoryList[j] == -1) {

??????????????? //頁面不在內存中且內存未滿->直接存入

??????????????? memoryList[j] = strList[i];

??????????????? //修改訪問情況

??????????????? isVisited = 1;

??????????????? missingCount ++;

??????????????? //展示

??????????????? printf("%d\n",strList[i]);

??????????????? showMemoryList(memoryList, phyNum);

??????????????? break;

??????????? }

??????? }

??????? if (!isVisited) {

??????????? //當前頁面還未被訪問過->需要進行頁面置換

??????????? //直接把這個頁面存到所記錄的下標中

??????????? memoryList[pointer] = strList[i];

??????????? //下標指向下一個

??????????? pointer ++;

??????????? //如果到了最后一個,將下標歸零

??????????? if (pointer > phyNum-1) {

??????????????? pointer = 0;

??????????? }??????????

??????????? missingCount ++;

??????????? replaceCount ++;

??????????? //展示

??????????? printf("%d\n",strList[i]);

??????????? showMemoryList(memoryList, phyNum);

??????? }

??? }

??? informationCount(missingCount, replaceCount, pageNum);//計算各項指標

}

int main(int argc, const char * argv[]) {?

//物理塊的數量

??? int phyBlockNum;

??? printf("請輸入物理塊數量:\n");

scanf("%d",&phyBlockNum);

??? //生成內存隊列數組

int memoryList[phyBlockNum];

??? //初始化內存狀態

??? initializeList(memoryList, phyBlockNum);

//showMemoryList(memoryList,phyBlockNum);

??? //頁面數量

??? int pageNum;

??? printf("請輸入要訪問的頁面總數:\n");

scanf("%d",&pageNum);

??? //保存頁面號數組

??? int pageNumStrList[pageNum];

??? int i;

//將要訪問的頁面號存入數組中

??? printf("請輸入要訪問的頁面號:\n");

??? for (i = 0; i < pageNum; i ++) {

??????? scanf("%d",&pageNumStrList[i]);

}

??? //顯示要訪問頁面號數組中內容

showList(pageNumStrList, pageNum);

??? int chose;

??? while (1) {

??????? printf("請選擇所需的置換算法:\n");

??????? printf("1.FIFO 2.退出\n");

??????? scanf("%d",&chose);

???????

??????? switch (chose) {

??????????? case 1:

//顯示要訪問頁面號數組中內容

??????????????? showList(pageNumStrList, pageNum);

//調用先進先出置換算法

??????????????? replacePageByFIFO(memoryList, phyBlockNum, pageNumStrList, pageNum);

??????????????? //重新初始化內存

??????????????? initializeList(memoryList , phyBlockNum);

??????????????? break;

??????????? default:

??????????????? return 0;

??????????????? break;

??????? }

??? }???

??? return 0;

}

編譯及執行過程以及結果截屏:

分析程序功能:

1.用戶輸入物理塊數量和要訪問的頁面總數。

2.用戶輸入要訪問的頁面號,將其存入一個數組中。

3.用戶選擇要使用的置換算法,目前只支持FIFO算法。

4.程序調用replacePageByFIFO函數來執行FIFO算法: a. 該函數通過遍歷頁面號數組,判斷頁面是否在內存中,如果在則不進行操作,如果不在則進行頁面置換。 b. 如果內存未滿,直接將頁面存入內存;如果內存已滿,將最早進入內存的頁面置換出去,并將新頁面存入內存。 c. 統計缺頁次數和置換次數,并展示當前內存狀態。

5.調用informationCount函數計算并展示各項指標,包括缺頁次數、缺頁率、置換次數和命中率。

6.重新初始化內存,回到步驟3,直到用戶選擇退出程序為止。

  1. 編程實現其它頁面置換算法(如最近最久未使用算法或最佳置換算法等),計算缺頁次數,缺頁率,置換次數和命中率。(1分)

#include <stdio.h>

#define MAX_PAGES 100

#define MAX_FRAMES 10

// 初始化頁面訪問序列

void initializePages(int pages[], int numPages) {

??? printf("請輸入頁面訪問序列(以-1結束):\n");

??? int i = 0;

??? do {

??????? scanf("%d", &pages[i]);

??????? i++;

??? } while (pages[i-1] != -1 && i < numPages);

}

// LRU算法

int lru(int pages[], int numPages, int numFrames) {

??? int frames[MAX_FRAMES] = {-1}; // 幀表

??? int lruCount[MAX_FRAMES] = {0}; // 記錄每個幀最后一次使用的時間

??? int numFaults = 0; // 缺頁次數

??? int numReplacements = 0; // 置換次數

??? int numHits = 0; // 命中次數

??? int time = 0; // 記錄時間

???

??? for (int i = 0; i < numPages; i++) {

??????? int page = pages[i];

??????? int j;

??????? for (j = 0; j < numFrames; j++) {

??????????? if (frames[j] == page) {

??????????????? numHits++;

??????????????? lruCount[j] = time;

??????????????? break;

??????????? }

??????? }

??????? if (j == numFrames) {

??????????? int lruIndex = 0;

??????????? for (int k = 1; k < numFrames; k++) {

??????????????? if (lruCount[k] < lruCount[lruIndex]) {

??????????????????? lruIndex = k;

??????????????? }

??????????? }

??????????? frames[lruIndex] = page;

??????????? lruCount[lruIndex] = time;

??????????? numFaults++;

??????????? numReplacements++;

??????? }

??????? time++;

??? }

???

??? printf("\nLRU算法結果:\n");

??? printf("缺頁次數:%d\n", numFaults);

??? printf("缺頁率:%f\n", (float)numFaults/numPages);

??? printf("置換次數:%d\n", numReplacements);

??? printf("命中率:%f\n\n", (float)numHits/numPages);

???

??? return numFaults;

}

// 最佳置換算法

int optimal(int pages[], int numPages, int numFrames) {

??? int frames[MAX_FRAMES] = {-1}; // 幀表

??? int numFaults = 0; // 缺頁次數

??? int numReplacements = 0; // 置換次數

??? int numHits = 0; // 命中次數

???

??? for (int i = 0; i < numPages; i++) {

??????? int page = pages[i];

??????? int j;

??????? for (j = 0; j < numFrames; j++) {

??????????? if (frames[j] == page) {

??????????????? numHits++;

??????????????? break;

??????????? }

??????? }

??????? if (j == numFrames) {

??????????? int replaceIndex = -1;

??????????? int found = 0;

??????????? for (int k = 0; k < numFrames; k++) {

??????????????? int m;

??????????????? for (m = i+1; m < numPages; m++) {

??????????????????? if (frames[k] == pages[m]) {

??????????????????????? found = 1;

??????????????????????? if (m > replaceIndex) {

??????????????????????????? replaceIndex = m;

??????????????????????? }

??????????????????????? break;

??????????????????? }

??????????????? }

??????????????? if (!found) {

??????????????????? replaceIndex = k;

??????????????????? break;

??????????????? }

??????????? }

??????????? frames[replaceIndex] = page;

??????????? numFaults++;

??????????? numReplacements++;

??????? }

??? }

???

??? printf("最佳置換算法結果:\n");

??? printf("缺頁次數:%d\n", numFaults);

??? printf("缺頁率:%f\n", (float)numFaults/numPages);

??? printf("置換次數:%d\n", numReplacements);

??? printf("命中率:%f\n\n", (float)numHits/numPages);

???

??? return numFaults;

}

int main() {

??? int pages[MAX_PAGES];

??? int numPages;

??? int numFrames;

???

??? printf("請輸入頁面數:");

??? scanf("%d", &numPages);

??? printf("請輸入幀數:");

??? scanf("%d", &numFrames);

???

??? initializePages(pages, numPages);

???

??? lru(pages, numPages, numFrames);

??? optimal(pages, numPages, numFrames);

???

??? return 0;

}

  1. 編程用動態分區鏈形式模擬動態分區管理中內存的分配和回收,采用3種算法(首次適應算法,最佳適應算法,最壞適應算法)實現。(附加題)

#include <stdio.h>

#include <stdlib.h>

#define MAX_SIZE 100

typedef struct Node {

??? int start;

??? int end;

??? int size;

??? int status; // 0表示未分配,1表示已分配

??? struct Node* next;

} Node;

Node* head = NULL;

// 初始化內存

void initMemory() {

??? head = (Node*)malloc(sizeof(Node));

??? head->start = 0;

??? head->end = MAX_SIZE;

??? head->size = MAX_SIZE;

??? head->status = 0;

??? head->next = NULL;

}

// 打印內存分配情況

void printMemory() {

??? Node* current = head;

??? while (current != NULL) {

??????? printf("[%d-%d] Size: %d ", current->start, current->end, current->size);

??????? if (current->status == 0) {

??????????? printf("Status: Free\n");

??????? } else {

??????????? printf("Status: Allocated\n");

??????? }

??????? current = current->next;

??? }

??? printf("\n");

}

// 首次適應算法分配內存

void* allocateFirstFit(int size) {

??? Node* current = head;

??? while (current != NULL) {

??????? if (current->status == 0 && current->size >= size) {

??????????? int remainingSize = current->size - size;

??????????? if (remainingSize > 0) {

??????????????? Node* newNode = (Node*)malloc(sizeof(Node));

??????????????? newNode->start = current->start;

??????????????? newNode->end = current->start + size;

??????????????? newNode->size = size;

??????????????? newNode->status = 1;

??????????????? newNode->next = current->next;

??????????????? current->start = newNode->end;

??????????????? current->size = remainingSize;

??????????????? current->next = newNode;

??????????? } else {

??????????????? current->status = 1;

??????????? }

??????????? return (void*)current->start;

??????? }

??????? current = current->next;

??? }

??? return NULL;

}

// 最佳適應算法分配內存

void* allocateBestFit(int size) {

??? Node* current = head;

??? Node* bestFitBlock = NULL;

??? int bestFitSize = MAX_SIZE + 1;

??? while (current != NULL) {

??????? if (current->status == 0 && current->size >= size && current->size < bestFitSize) {

??????????? bestFitBlock = current;

??????????? bestFitSize = current->size;

??????? }

??????? current = current->next;

??? }

??? if (bestFitBlock != NULL) {

??????? int remainingSize = bestFitBlock->size - size;

??????? if (remainingSize > 0) {

??????????? Node* newNode = (Node*)malloc(sizeof(Node));

??????????? newNode->start = bestFitBlock->start;

??????????? newNode->end = bestFitBlock->start + size;

??????????? newNode->size = size;

??????????? newNode->status = 1;

??????????? newNode->next = bestFitBlock->next;

??????????? bestFitBlock->start = newNode->end;

??????????? bestFitBlock->size = remainingSize;

??????????? bestFitBlock->next = newNode;

??????? } else {

??????????? bestFitBlock->status = 1;

??????? }

??????? return (void*)bestFitBlock->start;

??? }

??? return NULL;

}

// 最壞適應算法分配內存

void* allocateWorstFit(int size) {

??? Node* current = head;

??? Node* worstFitBlock = NULL;

??? int worstFitSize = -1;

??? while (current != NULL) {

??????? if (current->status == 0 && current->size >= size && current->size > worstFitSize) {

??????????? worstFitBlock = current;

??????????? worstFitSize = current->size;

??????? }

??????? current = current->next;

??? }

??? if (worstFitBlock != NULL) {

??????? int remainingSize = worstFitBlock->size - size;

??????? if (remainingSize > 0) {

??????????? Node* newNode = (Node*)malloc(sizeof(Node));

??????????? newNode->start = worstFitBlock->start;

??????????? newNode->end = worstFitBlock->start + size;

??????????? newNode->size = size;

??????????? newNode->status = 1;

??????????? newNode->next = worstFitBlock->next;

??????????? worstFitBlock->start = newNode->end;

??????????? worstFitBlock->size = remainingSize;

??????????? worstFitBlock->next = newNode;

??????? } else {

??????????? worstFitBlock->status = 1;

??????? }

??????? return (void*)worstFitBlock->start;

??? }

??? return NULL;

}

// 回收內存

void deallocate(void* addr) {

??? Node* current = head;

??? Node* prev = NULL;

??? while (current != NULL) {

??????? if (current->start == (int)addr) {

??????????? current->status = 0;

??????????? // 合并相鄰的空閑塊

??????????? if (prev != NULL && prev->status == 0) {

??????????????? prev->end = current->end;

??????????????? prev->size += current->size;

??????????????? prev->next = current->next;

??????????????? free(current);

??????????????? current = prev;

??????????? }

??????????? if (current->next != NULL && current->next->status == 0) {

??????????????? current->end = current->next->end;

??????????????? current->size += current->next->size;

??????????????? Node* temp = current->next->next;

??????????????? free(current->next);

??????????????? current->next = temp;

??????????? }

??????????? return;

??????? }

??????? prev = current;

??????? current = current->next;

??? }

}

int main() {

??? initMemory();

??? printMemory();

??? void* addr1 = allocateFirstFit(20);

??? printf("Allocated block: [0-20]\n");

??? printMemory();

??? void* addr2 = allocateBestFit(30);

??? printf("Allocated block: [20-50]\n");

??? printMemory();

??? void* addr3 = allocateWorstFit(40);

??? printf("Allocated block: [50-90]\n");

??? printMemory();

??? deallocate(addr2);

??? printf("Deallocated block: [20-50]\n");

??? printMemory();

??? deallocate(addr1);

??? printf("Deallocated block: [0-20]\n");

??? printMemory();

??? void* addr4 = allocateBestFit(70);

??? printf("Allocated block: [0-70]\n");

??? printMemory();

??? return 0;

}

三、實驗總結和體會(1分)

通過實際編寫程序實現內存分配與回收的算法,我更加理解了這些算法的原理和實現方式。其次,通過對比不同算法的性能,我能夠更加準確地選擇適合當前需求的算法。最后,我還學到了一些實際應用中的內存管理技巧和策略,為日后的工作打下了基礎。

在實驗過程中,我發現自己對于某些算法和概念的理解還不夠深入,需要進一步學習和加強。此外,我在實驗中遇到了一些問題,如編寫不完善的算法導致程序出錯等,這些問題提醒我需要加強對代碼質量和細節的把控。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/76289.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/76289.shtml
英文地址,請注明出處:http://en.pswp.cn/web/76289.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【MySQL】MySQL表的增刪改查(CRUD) —— 上篇

目錄 MySQL表的增刪改查&#xff08;CRUD&#xff09; 1. 新增&#xff08;Create&#xff09;/插入數據 1.1 單行數據 全列插入 insert into 表名 values(值, 值......); 1.2 單行數據 指定列插入 1.3 多行數據 指定列插入 1.4 關于時間日期&#xff08;datetime&am…

【MATLAB代碼例程】AOA與TOA結合的高精度平面地位,適用于四個基站的情況,附完整的代碼

本代碼實現了一種基于到達角(AOA) 和到達時間(TOA) 的混合定位算法,適用于二維平面內移動或靜止目標的定位。通過4個基站的協同測量,結合最小二乘法和幾何解算,能夠有效估計目標位置,并支持噪聲模擬、誤差分析和可視化輸出。適用于室內定位、無人機導航、工業監測等場景…

ModbusTCP 轉 Profinet 主站網關

一、 功能概述 1.1 設備簡介 本產品是 ModbusTCP 和 Profinet(M) 網關&#xff08;以下簡稱網關&#xff09;&#xff0c;使用數據映射 方式工作。 本產品在 ModbusTCP 側作為 ModbusTCP 從站&#xff0c;接 PLC 、上位機、 wincc 屏 等&#xff1b;在 Profin…

《AI大模型應知應會100篇》第25篇:Few-shot與Zero-shot使用方法對比

第25篇&#xff1a;Few-shot與Zero-shot使用方法對比 摘要 在大語言模型的應用中&#xff0c;**Few-shot&#xff08;少樣本&#xff09;和Zero-shot&#xff08;零樣本&#xff09;**是兩種核心的提示策略。它們各自適用于不同的場景&#xff0c;能夠幫助用戶在不進行額外訓練…

深入理解C++中string的深淺拷貝

目錄 一、引言 二、淺拷貝與深拷貝的基本概念 2.1 淺拷貝 2.2 深拷貝 在C++ 中, string 類的深淺拷貝有著重要的區別。 淺拷貝 深拷貝 string 類中的其他構造函數及操作 resize 構造 = 構造(賦值構造) + 構造(拼接構造) cin 和 cin.get 的區別 三、C++中string類的…

在Qt中驗證LDAP賬戶(Windows平臺)

一、前言 原本以為在Qt&#xff08;Windows平臺&#xff09;中驗證 LDAP 賬戶很簡單&#xff1a;集成Open LDAP的開發庫即可。結果臨了才發現&#xff0c;Open LDAP壓根兒不支持Windows平臺。沿著重用的原則&#xff0c;考慮遷移Open LDAP的源代碼&#xff0c;卻發現工作量不小…

《軟件設計師》復習筆記(11.4)——處理流程設計、系統設計、人機界面設計

目錄 一、業務流程建模 二、流程設計工具 三、業務流程重組&#xff08;BPR&#xff09; 四、業務流程管理&#xff08;BPM&#xff09; 真題示例&#xff1a; 五、系統設計 1. 主要目的 2. 設計方法 3. 主要內容 4. 設計原則 真題示例&#xff1a; 六、人機界面設…

UniRig ,清華聯合 VAST 開源的通用自動骨骼綁定框架

UniRig是清華大學計算機系與VAST聯合開發的前沿自動骨骼綁定框架&#xff0c;專為處理復雜且多樣化的3D模型而設計。基于強大的自回歸模型和骨骼點交叉注意力機制&#xff0c;UniRig能夠生成高質量的骨骼結構和精確的蒙皮權重&#xff0c;大幅提升動畫制作的效率和質量。 UniR…

LeetCode 443 壓縮字符串

字符數組壓縮算法詳解&#xff1a;實現與分析 一、引言 在處理字符數組時&#xff0c;我們常常遇到需要對連續重復字符進行壓縮的場景。這不僅可以節省存儲空間&#xff0c;還能提升數據傳輸效率。本文將深入解析一個經典的字符數組壓縮算法&#xff0c;通過詳細的實現步驟和…

alertManager部署安裝、告警規則配置詳解及告警消息推送

? java接受告警請求RestController RequestMapping("/alert") Slf4j public class TestApi {private static final DateTimeFormatter FORMATTER DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");RequestMappingpublic void sendTemplate(HttpServl…

數據庫勒索病毒威脅升級:企業數據安全防線如何用安當RDM組件重構

摘要&#xff1a;2025年Q1全球數據庫勒索攻擊量同比激增101.8%&#xff0c;Cl0p、Akira等團伙通過邊緣設備漏洞滲透企業核心系統&#xff0c;制造業、金融業等關鍵領域面臨數據加密與業務停擺雙重危機。本文深度解析勒索病毒對數據庫的五大毀滅性影響&#xff0c;結合安當RDM防…

thanos sidecar和receive區別?

Thanos Sidecar 和 Thanos Receive 是 Thanos 生態系統中兩個關鍵組件&#xff0c;但它們在架構中的作用和功能上有明顯的區別。以下是它們的主要區別&#xff1a; 1. Thanos Sidecar 功能&#xff1a; 與 Prometheus 集成&#xff1a; Sidecar 是一個部署在每個 Prometheus…

Unity入門筆記(緣更)

內容來源SiKi學院的Luna’s Fantasy 文章目錄 一、基礎知識1.準備2.基礎知識1.層級(Layer)2.軸心點3.預制體(Prefab)4.剛體組件(Rigidbody)5.碰撞器組件(BoxCollider) 二、代碼1.移動 一、基礎知識 1.準備 Unity安裝&#xff1a; https://unity.cn 2.基礎知識 1.層級(Layer…

使用VHD虛擬磁盤安裝雙系統,避免磁盤分區

前言 很多時候&#xff0c;我們對現在的操作系統不滿意,就想要自己安裝一個雙系統 但是安裝雙系統又涉及到硬盤分區,非常復雜,容易造成數據問題 虛擬機的話有經常用的不爽,這里其實有一個介于虛擬機和雙系統之間的解決方法,就是使用虛擬硬盤文件安裝系統. 相當于系統在機上…

ARINC818協議(五)

1.R_CTL,設置固定的0x44即可 2.Dest_ID:目的地D_ID,如果不需要目的地址&#xff0c;就設置為0&#xff1b;ADVB協議支持 多個視頻目的地址&#xff0c;廣播通信; 3.cs_ctl在FC-AV上不用 4.source_ID:S_ID [23:0]包含源實體的端口的地址標識&#xff1b;不用就設置為0. ADVB允許…

鴻蒙開發對于RelativeContainer高度設置‘auto‘后還是沒有自適應問題的解決方案

RelativeContainer設置高度為自適應‘auto’沒用生效&#xff0c;查看了官方文檔(文檔中心)也沒用給出明確的答案。只說了不能把錨點設置成父組件錨點&#xff08;__container__&#xff09;。也嘗試了使用guidline來替換父組件錨點&#xff0c;還是沒能自適應高度。 后來嘗試讓…

k8s教程3:Kubernetes應用的部署和管理

學習目標 理解Kubernetes中應用部署的基本概念和方法掌握Deployment、ReplicaSet、StatefulSet、DaemonSet、Job與CronJob等控制器的使用了解Helm作為Kubernetes的包管理工具的基本使用通過實際示例學習應用的部署、更新與管理 Kubernetes提供了一套強大而靈活的機制&#xff…

通過特定協議拉起 electron 應用

在 Android 通過 sheme 協議可以拉起其他應用。 electron 應用也可以通過類似特定協議被拉起。 在同時有 web、客戶端的應用里&#xff0c;可以通過這種方式在 web 拉起客戶端。 支持拉起客戶端 const PROTOCOL xxxif (process.defaultApp) {// 這里是開發環境&#xff0c;有…

算法備案的審核標準是什么?

隨著《互聯網信息服務算法推薦管理規定》等法規的出臺&#xff0c;算法備案成為了強制性備案&#xff0c;是產品合規上線的必要條件之一。本篇內容將從企業視角出發&#xff0c;分析算法備案的常見問題&#xff0c;意在對有備案需求的小伙伴們有所幫助。 一、誰需要做算法備案…

回顧與動機 - 為什么我們需要 Transformer

在接下來的旅程中,我們將一起探索深度學習領域最重要、最具影響力的模型架構之一——Transformer。從它的基本原理出發,逐步深入,最終能夠親手實現一個文本生成模型。 本系列教程假設你已經具備一定的深度學習基礎,了解神經網絡、損失函數、優化器等基本概念,并且熟悉 Py…