交换两段连续(不连续)内存
来源:互联网 发布:网络虚拟电话软件 编辑:程序博客网 时间:2024/04/30 09:46
文章作者:Yx.Ac 文章来源:勇幸|Thinking (http://www.ahathinking.com) 转载请注明,谢谢合作。
在《编程珠玑,第二版》和《编程之美》中都有关于交换两段连续的内存块的题目,而且非常经典,交换两段连续内存块的问题又可以延伸到交换两段不连续内存块的问题,无论是哪种情况都需要一个基本操作:反转内存块。
反转内存时,比较简单,可以两个指针同时走,也可以一个指针,随意,实现如下:
// reverse the memory block // goal: |12345| -> |54321|void * reverseMemory(void *pMemory, const size_t memSize){ if(NULL == pMemory) return pMemory; if(memSize < 2) return pMemory; char * beg = static_cast<char *>(pMemory); char * end = beg + memSize -1; for(; beg < end; ++beg, --end) { char memTmp = *beg; *beg = *end; *end = memTmp; } return pMemory;}
其中,函数的两个形参分别为要反转内存的起始地址和内存块的大小。返回值类型为void*,指向反转内存块的起始地址。
实现了反转内存块这一基本操作后,我们就可以用它来交换两段连续的内存,从而解决类似“数组循环移位”的问题。具体算法在编程珠玑和编程之美中都有详细介绍,这里简单说一下:
假设有连续的内存块M和N形如:|----M---|--------N---------|
- 首先反转内存块M:M’=reverse(M)
- 反转内存块N:N’=reverse(N)
- 对整个内存块M’ N’进行反转:(M’N’)’ = NM
举例:M=”abc”, N=”1234”
- M’=reverse(M)=”cba”
- N’=reverse(N)=”4321”
- (M’N’)’=(cba4321)’=”1234abc”
实现如下:
// swap two adjacent memory block// goal: |*****|######| -> |######|*****|void * swapAdjacentMemory(void *pMemory, const size_t headSize, const size_ttotalSize){ if(NULL == pMemory) return pMemory; if(totalSize < 2) return pMemory; if(headSize >= totalSize) return pMemory; char* pStart = static_cast<char*>(pMemory); reverseMemory(pStart,headSize); reverseMemory(pStart+headSize,totalSize-headSize); reverseMemory(pStart,totalSize); return pMemory;}
函数的形参为内存起始地址pMemory、头长度headSize和内存总长度totalSize,其中headSize就相当于“数组循环移位问题”中移位大小,如右移4位等同于headSize为4。
现在我们明白了如何交换两段连续的内存,那么如何交换两段不连续的内存呢?
形如:有内存MAN三块:|----M---|----A----|-----N------|,我们要交换M,N,保持A不动。
类似于交换两段连续内存,仔细地想一下并不难,算法如下:
- 反转内存块M:M’=reverse(M)
- 反转A:A’=reverse(A)
- 反转N:N’=reverse(N)
- 反转M’A’N’:(M’A’N’)’=NAM
实现如下:
// swap two nonadjacent memory block// goal: |*****|$$$$|######| -> |######|$$$$|*****|void* swapNonAdjacentMemory(void *pMemory, const size_t headSize, const size_tendSize, const size_t totalSize){ if(NULL == pMemory) return pMemory; if(totalSize < 3) return pMemory; if(headSize >= totalSize || endSize >= totalSize) return pMemory; if(totalSize < (headSize+endSize)) return pMemory; char* pStart = static_cast<char *>(pMemory); reverseMemory(pStart,headSize); reverseMemory(pStart+headSize,totalSize-headSize-endSize); reverseMemory(pStart+totalSize-endSize,endSize); reverseMemory(pStart,totalSize); return pMemory;}
实现之后,我们写一个测试用例来验证一下:
#include <iostream>using namespace std;#define MAXBUFFERSIZE 100void main(){//这里我们将所有的测试用例放在一个字符串数组中,循环便可以测试所有的字符串//如果要修改字符串或增加新的测试用例,只需修改这个表即可static const char* stringArr[]={"","ab","abc","abc1234"};void * resultArr = malloc(MAXBUFFERSIZE); // store the test resultif(NULL == resultArr) return ;size_t arrLen = sizeof(stringArr)/sizeof(*stringArr);// test swapAdjacentMemory |for(size_t i = 0; i < arrLen; ++i){memset(resultArr,0,MAXBUFFERSIZE);memcpy(resultArr,stringArr[i],strlen(stringArr[i]));swapAdjacentMemory(resultArr,2,strlen(*(stringArr+i)));printf("%s\n",resultArr);}// test swapNonAdjacentMemoryfor(size_t i = 0; i < arrLen; ++i){memset(resultArr,0,MAXBUFFERSIZE);memcpy(resultArr,stringArr[i],strlen(stringArr[i]));swapNonAdjacentMemory(resultArr,2,2,strlen(stringArr[i]));printf("%s\n",resultArr);}free(resultArr);}
反转内存 & 交换内存 这一操作很重要,后面的文章我们会看到其灵活运用的效果。
0 0
- 交换两段连续(不连续)内存
- 交换两段连续(不连续)内存<转>
- 动态分配二维数组 连续内存,不连续内存实现
- memcpy不能拷贝不连续的内存
- POJ 2593 Max Sequence POJ 2479 Maximum sum (线性dp 最大连续两不重叠子段和)
- poj 2479 两段连续子序列的最大和
- 简单寻找连续段
- 交换两段不连续的内存块(Swap Nonadjacent Memory Blocks)
- 交换两段不连续的内存块(Swap Nonadjacent Memory Blocks)
- 按时间段统计,不连续的日期要补上
- HDU2845_Beans【不连续的最大子段和】【元素压缩】
- hdu2845 DP最大不连续子段和
- 连续
- 连续声明的几个int型变量内存地址不连续
- SQL查询连续号码段
- SQL查询连续号码段
- 最大连续子段和
- 最大连续子段和
- iOS swift 创建各种变量,常量,字典,数组等
- Unix & Linux笔记(8)
- editplus+phpCB 简单的PHP代码格式化工具
- Android学习系列(24)--App列表之下拉刷新
- ckeditor 去除自带的<p>标签
- 交换两段连续(不连续)内存
- Html5刮刮卡效果(移动端、PC端)
- acm_猴子与箱子
- 图的邻接矩阵表示 DFS 和BFS C++实现
- 设计模式中的六大原则
- 21. SpringMVC_如何确定目标方法POJO类型参数(无写笔记)
- 冒泡排序
- (面试)程序员面试总结汇总(待整理)
- redis+twemproxy自动分片(一致性hash)