1. C/c++动态分配内存
malloc/free
malloc分配内存后返回的指针为void*类型,需要强转
同一片内存块不能被重复释放
若指针指向NULL,重复free该指针是没有问题的,因为它指向的内存块并不存在
//注意需要做类型强转
int* a = (int*)malloc(5 * sizeof(int));
for(int i = 0; i < 5; i++)
{
a[i] = 3 + i;
}
printf("the address of a is %p\n", a);
free(a);
a = NULL;
free(a);
//free(a);
new/delete
删除数组时,要带上中括号delete[] p
delete删除指针指向的内存后,防止指针变成野指针,需要将指针指向NULL,p = NULL
int* a = new int(5);
printf("a = %d\n", *a);
printf("the address of a is %p\n", a);
delete a;
int* b = new int[5];
for(int i = 0; i < 5; i++)
{
b[i] = i + 3;
}
printf("the address of b is %p\n", b);
delete [] b;
b = NULL;
2. 重写自己的String类,加深对字符串内部机理的了解
注意,必须先申请内存,在赋值,且需要判断为空
String的构造函数
MyString::MyString(const char* str)
{
if(str == NULL)
{
m_data = new char[1];
m_data[0] = '\0';//结束符
}
else
{
int len = strlen(str);
m_data = new char[len + 1];
strcpy(m_data, str);
m_data[len] = '\0';
}
}
String的拷贝构造函数
MyString::MyString(const MyString& another)
{
m_data = new char[strlen(another.m_data)];
strcpy(m_data, another.m_data);
}
赋值运算符
MyString& MyString::operator = (const MyString& rhs)
{
//判断是否为本身
if(this == &rhs)
{
return *this;
}
//先删除原来的内存
delete [] m_data;
m_data = new char[strlen(rhs.m_data)];
strcpy(m_data, rhs.m_data);
return *this;
}
析构函数
MyString::~MyString()
{
delete [] m_data;
m_data = NULL;
}
字符串逆序
void PrintReverse(char* str)
{
if(str == NULL)
{
printf("WARN:the string is empty!");
}
int j = strlen(str)-1;
for(int i = 0; i < strlen(str)/2; i++)
{
char tmp = 0;
tmp = str[i];
str[i] = str[j];
str[j] = tmp;
j--;
}
}
3. 数据结构之链表
已知链表头结点,将链表逆序
MyNode* ReverseList(MyNode* pHead)
{
//链表不存在节点或只有一个节点的情况
if(pHead == NULL || pHead->pNext == NULL)
{
return pHead;
}
//一般使用三个临时指针来实现倒序
MyNode* p1 = pHead;
MyNode* p2 = pHead->pNext;
MyNode* p3 = p2->pNext;
p1 = NULL;
while(p3 != NULL)
{
p2->pNext = p1;
p1 = p2;
p2 = p3;
p3 = p3->pNext;
}
p2->pNext = p1;
pHead = p2;
return pHead;
}
合并两个有序的链表
MyNode* Merge(MyNode* pA, MyNode* pB)
{
MyNode* pHead = NULL;
//若链表A为空,则返回值为链表B
if(pA == NULL)
{
pHead = pB;
}
//若链表B为空,则返回值为链表A
if(pB == NULL)
{
pHead = pA;
}
//若都不为NULL
//初始化三个临时变量
MyNode* p1 = NULL;//记录当前头结点的下一个节点
MyNode* p2 = NULL;//记录另一个链表的头结点
//若链表A的头结点值小于等于B的头结点值(按升序排列)
if(pA->data < pB->data)
{
pHead = pA;
p1 = pHead->pNext;
p2 = pB;
}
else
{
pHead = pB;
p1 = pHead->pNext;
p2 = pA;
}
MyNode* pCur = pHead;
while(p1 != NULL && p2 != NULL)
{
//比较p1和p2节点
if(p1->data <= p2->data)
{
pCur->pNext = p1;
pCur = p1;
p1 = p1->pNext;
}
else
{
pCur->pNext = p2;
pCur = p2;
p2 = p2->pNext;
}
}
//循环结束后,必定有一个节点为NULL
if(p1 != NULL)
{
pCur = p1;
}
else if(p2 != NULL)
{
pCur = p2;
}
return pHead;
}