链表相关(基本操作+翻转链表+奇偶分类+回文链表判断)

链表基本操作

创建链表

  • 头节点只有next 数据域无内容,一开始赋值给pre
  • 有一个pre,用来连接新生成的节点
  • 用new生成新节点
  • 每次循环更新当前节点为pre节点
#include<vector>
#include<iostream>
using namespace std;

struct node {
	int data;
	node* next;
};
//创建链表

node* create(vector<int> &arr) {
	node *p, *pre, *head;//当前结点/前驱结点/头结点
	head = new node;//创建头节点
	head->next = NULL;//头节点不需要数据域,指针初始化为NULL
	pre = head;
	for (int i = 0; i < arr.size(); i++) {
		p = new node;
		p->data = arr[i];
		p->next = NULL;
		pre->next = p;
		pre = p;
	}
	return head;

}
int main() {
	vector<int> arr;
	arr.push_back(5);
	arr.push_back(3);
	arr.push_back(6);
	node* L = create(arr);
	node*p = L->next;
	while (p) {
		printf("%d", p->data);
		p = p->next;
	}
	return 0;
}

遍历链表

  • 从头节点的下一个节点开始遍历
  • 分析每个节点的内容、记录
  • 更新当前节点
  • 退出条件是当前节点为NULL
int search(node*head, int x) {
	node* p = head->next;
	int cnt = 0;
	while (p) {
		if (p->data == x) {
			cnt++;
		}
		p = p->next;
	}
	return cnt;
}

插入节点

  • 特别注意要找的是插入的位置的前一个节点
  • 不知道链表的前一个节点就无法进行增删操作
void insert(node* head, int pos, int x) {
	node* p = head;
	for (int i = 0; i < pos - 1; i++) {
		p = p->next;//找到插入位置的前一个节点
	}
	node*newNode = new node;//新建节点
	newNode->data = x;
	newNode->next = p->next;
	p->next = newNode;
}

删除节点

  • 设前置节点
  • 找到的情况释放内存,记得要重新指定p的指向为pre->next
void del(node* head, int x) {
	node *p = head->next;
	node* pre = head;
	while (p) {
		if (p->data == x) {
			pre->next = p->next;
			delete(p);
			p = pre->next;
		}
		else {
			pre = p;
			p = p->next;
		}
	}

}

题目

反转链表

  • 俩指针 p q。p在q前。
  • 每次把q的next指向p
  • 把pq向后移动一位
  • 每次最开始要保存qnext
 ListNode* reverseList(ListNode* head) {
       ListNode*p=NULL,*q=head;
       while(q){
           ListNode*t=q->next;
           q->next=p;
           p=q;
           q=t;
       }
       return p;
    }

奇偶链表

把一个链表的全部奇数项排在全部偶数项前面

  • 四个四个一处理,分链表元素奇数个和偶数个两种情况讨论。
ListNode* oddEvenList(ListNode* head) {
        if(head==NULL) return NULL;
        if(head->next==NULL) return head;
        ListNode*p1=head;
        ListNode*p2=head->next;
        ListNode*t=p2;//存放偶数开头
        while(p1 && p2 && p1->next && p2->next){
             p1->next=p2->next;
             p2->next=p1->next->next;
             p1=p1->next;
             p2=p2->next;
        }
       p1->next=t;
       return head;
    }

回文链表判断

  • 找到中间链表(奇偶情况讨论)
  • 反转前半部分链表
  • 同时遍历前半部分和后半部分链表,比较是否相同
bool isPalindrome(ListNode* head) {
	if (head == NULL)return false;
	if (head->next == NULL)return true;
	int cnt = 0;
	ListNode*p=head, *q;
	while (p) {
		cnt++;
		p = p->next;//cnt为元素个数
	}
	int midIndex = cnt / 2;//中间元素(从1开始计树)的前一个
	
	ListNode*midP = head;
	for (int i = 1; i <= midIndex - 1; i++) {
		midP = midP->next;//奇数个的话指向中间元素前一个,偶数个的话指向靠左的那个
	}
	ListNode*p1, *p2;//最后用于遍历的指针
	if (cnt % 2 == 0) {//根据情况指定从左往右遍历的指针
		p2 = midP->next;
	}
	else {
		p2 = midP->next->next;
	}
	p = NULL;
	q = head;
	for (int i = 1; i <= midIndex; i++) {//反转
		ListNode*t = q->next;
		q->next = p;
		p = q;
		q = t;
	}
	//指定从右往左遍历的指针
	p1 = p;
	//比较
	bool flag = true;
	while (p1 && p2) {
		if (p1->val != p2->val) flag = false;
		p1 = p1->next;
		p2 = p2->next;
	}
	return flag;

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值