链表的结构定义:链表是由若干哥节点穿起来的,是逻辑上串联到一起的,每个节点处存储两部分信息,(第一部分是我们的数据信息,第二部分是我们称作next指针用来找到下一个链表节点)。
链表的结构操作:
删除操作:很简单只需要让head指向第三个节点即可
插入:(都是用指针来操作的
)插入的时候注意内存泄漏的问题,就是先指向谁,可能会丢失下一节点的地址
#include<stdio.h>
#include<stdlib.h>
typedef struct Node
{
int data;
struct Node* next;//这里是链表的数据定义
}Node;
Node* getNewNode(int val)
{
Node* p = (Node*)malloc(sizeof(Node));
p->data = val;
p->next = NULL;
return p;
}
void clear(Node* head)
{
if (head == NULL) return;
for (Node* p = head, *q; p; p=q )//遍历每一个节点
{
q = p->next;
free(p);
}
return;
}
//插入操作
Node* insert(Node* head,int pos,int val)
{
if (pos == 0)
{
Node* p = getNewNode(val);
p->next = head;
return p;
}
Node* p = head;
for (int i = 1; i < pos; i++) p = p->next;//p指针指向了待插入的前一个节点
Node* node = getNewNode(val);
node->next = p->next;
p->next = node;//这里要先node指向后一段 然后前一段再指向node防止出现内存泄露
return head;
}
int main()
{
return 0;
}
以上是无头链表的思想
还有单向循环链表
head节点指向最后一个节点
双向链表 就是在他的结构定义里面由两个指针,一个向前另外一个向后
实现链表反转
利用虚拟节点来进行操作
ListNode* reverseList(ListNode* head) {
ListNode New_head, * q, * p;
New_head.next = NIULL;
while (p)
{
*q = p->next;//拿一个指针 记录p的下一个节点
p->next = New_head.next;//把p现在的指针拿到虚拟头节点的前面
New_head.next = p;//再把虚拟头节点断开 放到移动的p身上
p=q;//再让p回去 到q 即刚才的下一个节点
}
技巧:如果把一个链表放到另一个节点的后面时候常用的操作是这里我们把val放在pos后面
val->next=pos->next;
pos->next=val;
你细品
class Solution {
public:
int getlenght(ListNode* head)
{
int n=0;
while(head)
{
n+=1;
head=head->next;
}
return n;
}
ListNode* rotateRight(ListNode* head, int k) {
if(head==NULL) return head;
int n=getlenght(head);
k%=n ;
if(k==0)return head;
ListNode *p=head,*q=head;
for(int i =0;i<=k;i++) p=p->next;
while(p) p=p->next,q=q->next;
p=q->next;
q->next=NULL;
q=p;
while(q->next!=NULL) q=q->next;
q->next=head;
return p;
}
};