1.指针和引用
指针指向存放变量的值的地址
# include <iostream>
using namespace std;
int main()
{
int a=10;
int *p=&a;
*p+=5;
cout<<*p<<endl;
return 0;
}
输出 15
2.数组名是一种特殊的指针 指针可以做运算
# include <iostream>
using namespace std;
int main()
{
int a[5]={1,2,3,4,5};
for(int i=0;i<5;i++)cout<<*(a+i)<<endl;
//打括号是一种习惯 实际此处不打也行
return 0;
}
输出 1 2 3 4 5
引用和指针类似,相当于给变量起了个别名
# include <iostream>
using namespace std;
int main()
{
int a=10;
//int *p=&a;//c语言的写法
int &p = a;//别名 ,引用
cout<<*p<<endl;
return 0;
}
同输出10
3.链表的实现
# include <iostream>
# include <string.h>
using namespace std;
const int N = 10010;
struct Node
{
int val;
Node *next;
}*head;
int main()
{
for(int i=1;i<=5;i++){
Node *p =new Node();
p->val =i;
p->next = head;
head = p;
}
//遍历
for(Node *p=head; p!=0; p=p->next)
cout<<p->val<< endl;
return 0;
}
new返回对应的地址
p是指针 调用结构体里面的变量要用-> 一般则是p.next
头结点一般指第一个结点的地址而不是它的值
4.链表的增加和删除
添加节点
//添加结点
Node *u;
u->next=head;
head=u;
链表的删除->指的是遍历的时候遍历不到
//删除节点
head->next = head->next->next;
5.反转链表
这里我们用两个指针依次往后移
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if(!head||!head->next)return head;
ListNode* p=head, *q=p->next;
while(q){
ListNode* o=q->next;
q->next=p;
p=q;q=o;
}
head->next=NULL;
return p;
//for(auto p=head; p!=0; p=p->next)
//cout<<p->val<< endl;//遍历
}
};
while里面用了o指针进行临时的存储while(q)的意思是q不为NULL时进行循环
if(!head||!head->next)是防止链表为空或者链表只有一个节点的情况
6.在O(1)时间删除链表结点
原理是先复制下一个节点 然后指针引向下下个节点(题目不知道头节点)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
void deleteNode(ListNode* node) {
node->val=node->next->val;//伪装
node->next=node->next->next;
//删除下一个点
}
};
7.合并两个排序的链表
输入两个递增排序的链表,合并这两个链表并使新链表中的结点仍然是按照递增排序的。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* merge(ListNode* l1, ListNode* l2) {
auto dummy = new ListNode(-1),tail =dummy;
while(l1&&l2)
if(l1->val<l2->val){
tail= tail->next=l1;
l1=l1->next;
}
else{
tail =tail->next =l2;
l2 = l2->next ;
}
if(l1)tail->next =l1;
if(l2)tail->next = l2;
return dummy ->next;
}
};
运用虚拟头节点 同时将两个链表拆分并逐个比较 成为一个新的链表
8.两个链表的第一个公共结点
使用双指针解法最巧妙
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *findFirstCommonNode(ListNode *headA, ListNode *headB) {
auto p=headA,q=headB;
while(p!=q){
if(p)p=p->next;
else p=headB;
if(q)q=q->next;
else q=headA;
}
return q;
}
};
9.删除链表中重复的节点
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* deleteDuplication(ListNode* head) {
auto dummy= new ListNode(-1);
auto p=dummy;
dummy->next=head;
while(p->next){
auto q=p->next;
while(q->next&&q->next->val==p->next->val)q=q->next;
if(q==p->next)p=q;
else p->next=q->next;
}
return dummy->next;
}
};