[C++学习]剑指offer13题的学习笔记
2017-02-27 21:31
232 查看
问题描述:用O(1)时间删除链表中的指定结点。
下面是学习遇到的困惑和解决方法:
1. 如何去引用结构体中的成员。
首先定义了一个结构体:
struct ListNode{int m_nValue;ListNode* m_pNext;};
利用->和.去引用结构体中的成员:
其中“->“用于指针类型的类的实例,而“.“用于普通对象(非指针类型)的引用。
两者最大的区别是->前面放的是指针,而.前面跟的是结构体变量
例如:
2. 题目给出的函数是 voidDeleteNode(ListNode** pListHead,ListNode* pToBeDeleted);**代表指向指针的指针,该如何认识它?
参考文章(让你不再害怕指针——C指针详解(经典,非常详细))
将函数的传参写出:
ListNode** pListHead=& pNode1;
&: &a的运算结果是一个指针,指针的类型是a的类型加个*
*:*p简而言之是p所指向的东西。
了解指针需要了解指针的四个内容:
a.指针的类型:把指针的名字去掉
b.指针所指向的类型:去掉指针的名字+名字左边的*
c.指针本身所占的内存区
d.指针所指的内存区:
因此,可以看出ListNode是指向pNode1的指针的指针,也相当于:
ListNode* pListHead =pNode1;但前者在引用值:
(*pListHead)->m_nValue。后者在引用值:pListHead->m_nValue。
3. 为什么要指针和值分别赋值?不用直接将结点赋值?也就是说
pToBeDeleted->m_nValue =pToBeDeleted->m_pNext->m_nValue;
pToBeDeleted->m_pNext =pToBeDeleted->m_pNext->m_pNext;
//pToBeDeleted = pToBeDeleted->m_pNext;//为什么分开赋值可以成功,但是直接赋值就不可以?
我想应该函数值传参的原因,直接赋值,其实是把pToBeDelete转换到了next上,对实际的list未能产生影响。而逐个赋值涉及到了指针,由此改变了list
学习C++primer函数传参那节可以解决这个困惑。函数的参数传递分为两类,一是值传递,二是引用传递。值传递是对变量的改动,并不会改变实参值;而引用传递与变量初始化的机理一致,其实是一个对象的别名,可以通过改变其引用来改变实参值。通过下面的例子去理解它:
void reset(int *ip){ *ip = 0; //改变了指针ip所指对象的值 ip = 0;//ip的指向改变}reset(&i);//改变的是i的值,而非i的地址int i = 42;cout << i << endl; //输出为0
int* ip=&i;将ip指向i
返回问题中来pToBeDeleted = pToBeDeleted->m_pNext;改变了形参所指的对象,未能对实参产生影响。pToBeDeleted->m_nValue =pToBeDeleted->m_pNext->m_nValue;改变了形参所指对象的值。
4.书上的参考答案为什么必须删除下个结点?
我试了一下不删除结点也对,没有报错。可能涉及到了空间释放、安全等问题。
下面是学习遇到的困惑和解决方法:
1. 如何去引用结构体中的成员。
首先定义了一个结构体:
struct ListNode{int m_nValue;ListNode* m_pNext;};
利用->和.去引用结构体中的成员:
ListNode* p=new ListNode; p->m_nValue = i; p->m_pNext = NULL; ListNode p; p.m_nValue = i; p.m_pNext = NULL;
其中“->“用于指针类型的类的实例,而“.“用于普通对象(非指针类型)的引用。
两者最大的区别是->前面放的是指针,而.前面跟的是结构体变量
例如:
struct A { int a; int b; }; A *point =malloc(sizeof(struct A)); cout<<point->a<<endl;//输出1 A object; cout<<object.a <<endl;//输出1
2. 题目给出的函数是 voidDeleteNode(ListNode** pListHead,ListNode* pToBeDeleted);**代表指向指针的指针,该如何认识它?
参考文章(让你不再害怕指针——C指针详解(经典,非常详细))
将函数的传参写出:
ListNode** pListHead=& pNode1;
&: &a的运算结果是一个指针,指针的类型是a的类型加个*
*:*p简而言之是p所指向的东西。
了解指针需要了解指针的四个内容:
a.指针的类型:把指针的名字去掉
b.指针所指向的类型:去掉指针的名字+名字左边的*
c.指针本身所占的内存区
d.指针所指的内存区:
因此,可以看出ListNode是指向pNode1的指针的指针,也相当于:
ListNode* pListHead =pNode1;但前者在引用值:
(*pListHead)->m_nValue。后者在引用值:pListHead->m_nValue。
3. 为什么要指针和值分别赋值?不用直接将结点赋值?也就是说
pToBeDeleted->m_nValue =pToBeDeleted->m_pNext->m_nValue;
pToBeDeleted->m_pNext =pToBeDeleted->m_pNext->m_pNext;
//pToBeDeleted = pToBeDeleted->m_pNext;//为什么分开赋值可以成功,但是直接赋值就不可以?
我想应该函数值传参的原因,直接赋值,其实是把pToBeDelete转换到了next上,对实际的list未能产生影响。而逐个赋值涉及到了指针,由此改变了list
学习C++primer函数传参那节可以解决这个困惑。函数的参数传递分为两类,一是值传递,二是引用传递。值传递是对变量的改动,并不会改变实参值;而引用传递与变量初始化的机理一致,其实是一个对象的别名,可以通过改变其引用来改变实参值。通过下面的例子去理解它:
void reset(int *ip){ *ip = 0; //改变了指针ip所指对象的值 ip = 0;//ip的指向改变}reset(&i);//改变的是i的值,而非i的地址int i = 42;cout << i << endl; //输出为0
int* ip=&i;将ip指向i
void reset(int &ip) { ip = 0; } int i = 42; reset(i);//改变的是i的值,而非i的地址 cout << i << endl; //输出为0int& ip=i;其实ip是i的别名,可以通过改变ip来改变i。
返回问题中来pToBeDeleted = pToBeDeleted->m_pNext;改变了形参所指的对象,未能对实参产生影响。pToBeDeleted->m_nValue =pToBeDeleted->m_pNext->m_nValue;改变了形参所指对象的值。
4.书上的参考答案为什么必须删除下个结点?
我试了一下不删除结点也对,没有报错。可能涉及到了空间释放、安全等问题。
相关文章推荐
- [c++学习]剑指offer1题的学习笔记
- #数据结构与算法学习笔记#剑指Offer1.5:二维数组中的查找(C++)
- [C++学习]剑指offer8题学习笔记
- C++ FAQ学习笔记 13 章 运算符重载
- 【C++ rimer 学习笔记】ch13 复制控制
- 剑指offer学习笔记2
- (C++)剑指offer-13:调整数组顺序使奇数位于偶数前面(代码的完整性)
- c++学习笔记(13.专题三经典问题解析)
- 剑指offer学习笔记1
- 剑指offer题解C++【13】调整数组顺序使奇数位于偶数前面
- C++ 学习笔记(13)拷贝构造函数、拷贝赋值运算符、移动构造函数、移动赋值运算符、析构函数、右值引用、引用限定符
- C/C++学习笔记13:传递动态内存(1)
- C++学习笔记13 C++ 类的静态成员
- C++学习笔记13:类继承和派生、虚函数
- Effective C++ 学习笔记(13)
- C++学习笔记(13)——利用对象、引用、指针调用虚函数
- 【C++学习笔记】13_指针的运算
- C++学习笔记13-类继承
- 【C++】学习笔记草稿版13(运算符重载提高篇)
- C++学习笔记13 STL Set和Map