C++指针和引用和链表实现

 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;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mr丶锤子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值