文章目录
一、单向链表
1. 链表结点的定义
C++
struct ListNode{
int data;
ListNode *next;
};
Java
class ListNode<E>{
E val;
ListNode<E> next;类似
ListNode(E val){
this.val = val;
}
}
2. 插入结点
C++
void InsertNode(ListNode *hd, ListNode *a, int x) {
if (x == 0) {
a->next = hd;
hd = a;
return;
}
for (int i=1;i<x && hd->next!=NULL;i++) {
hd = hd->next;
}
a->next = hd->next;
hd->next = a;
}
Java
void InsertNode(ListNode hd, ListNode, a, int x) {
if (x == 0) {
a.next = hd;
hd = a;
return;
}
for (int i=1;i<x && hd.next!=null;i++) {
hd = hd.next;
}
a.next = hd.next;
hd.next = a;
}
3. 删除结点
C++
ListNode *DeleteNode(ListNode *hd, int x) {
for (int i=1;i<x;i++) {
if (hd == NULL) return NULL;
hd = hd->next;
}
ListNode *ret = hd->next;
hd->next = hd->next->next;
return ret;
}
Java
ListNode DeleteNode(ListNode hd, int x) {
for (int i=1;i<x;i++) {
if (hd == null) return null;
hd = hd.next;
}
ListNode ret = hd.next;
hd.next = hd.next.next;
return ret;
}
4. 查找结点
C++
ListNode *FindNode(ListNode *hd, int x){
for(int i=1;i<=x;i++){
hd = hd->next;
}
return hd;
}
Java
ListNode FindNode(ListNode hd, int x) {
for (int i=1;i<=x;i++) {
hd = hd.next;
}
return hd;
}
5. 链表的逆置
ListNode *ReverseList(ListNode *hd){
if(hd->next == NULL) return hd;
ListNode *Rhead = NULL;
hd = hd->next;
while(hd != NULL){
ListNode *temp = hd;
hd = hd->next;
temp->next = Rhead;
Rhead = temp;
}
hd = new ListNode;
hd->data = 0;
hd->next = Rhead;
return hd;
}
6. 查找倒数第 k 个结点
ListNode *kthFromEnd(ListNode *hd, int k){
ListNode *tag = hd;
while(k>1){
hd = hd->next;
}
while(hd->next != NULL){
hd = hd->next;
tag = tag->next;
}
return tag;
}
7. 判断是否有环
ListNode *HaveLoop(ListNode *hd){
ListNode *tag = hd;
while(tag->next!=NULL && tag!=NULL){
tag = tag->next->next;
hd = hd->next;
if(hd == tag) return hd;
}
return NULL;
}
8. 查找环的入口
ListNode *FindLoopEntry(ListNode *hd){
ListNode *tag = HaveLoop(hd);
if(tag == NULL) return NULL;
while(hd != tag){
hd = hd->next;
tag = tag->next;
}
return tag;
}
9. 测试程序
void PrintList(ListNode *hd){
while(hd->next != NULL){
hd = hd->next;
cout << hd->data << " -> ";
}
cout << endl;
}
int main(void){
ListNode *head = new ListNode;
head->data = 0;
head->next = NULL;
for(int i=1;i<=5;i++){
cin >> n;
ListNode *Node = new ListNode;
Node->data = n;
Node->next = NULL;
InsertNode(head,Node,ListLen+1);
}
PrintList(head);
for(int i=1;i<=2;i++){
cin >> n;
DeleteNode(head,n);
PrintList(head);
}
for(int i=1;i<=2;i++){
cin >> n;
cout << FindNode(head,n)->data << endl;
}
head = ReverseList(head);
PrintList(head);
cin >> n;
ListNode *k = kthFromEnd(head,n);
cout << k->data << endl;
return 0;
}
class Solution {
public void deleteNode(ListNode node) {
node.val = node.next.val;
node.next = node.next.next;
}
}
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode head1 = l1;
ListNode head2 = l2;
ListNode head3 = new ListNode();
ListNode l3 = head3;
int k = 0;
while (head1 != null || head2 != null) {
int x = head1 == null ? 0 : head1.val;
int y = head2 == null ? 0 : head2.val;
int sum = x + y + k;
l3.next = new ListNode(sum%10);
k = sum / 10;
l3 = l3.next;
if (head1 != null) head1 = head1.next;
if (head2 != null) head2 = head2.next;
}
if (k == 1) l3.next = new ListNode(1);
return head3.next;
}
}
二、双向链表
1. 链表结点的定义
struct ListNode{
int data;
ListNode *next;
ListNode *prev;
};
2. 插入结点
//p决定了插入到左侧还是右侧
void InsertNode(ListNode *hd, ListNode *a, int x, int p){
if(x<=0 || x>ListLen+1) return NULL;
for(int i=1;i<x;i++){
hd = hd->next;
}
ListLen++;
if(!p){
a->next = hd;
a->prev = hd->prev;
hd->prev->next = a;
hd->prev = a;
}
else{
a->next = hd->next;
a->prev = hd;
hd->next->prev = a;
hd->next = a;
}
}
2.删除结点
ListNode *DeleteNode(ListNode *hd, int x){
if(x<=0 || x>ListLen) return NULL;
for(int i=1;i<x;i++){
hd = hd->next;
}
ListLen--;
ListNode *tag = hd;
hd->prev->next = hd->next;
hd->next->prev = hd->prev;
return tag;
}
3. 查找结点
ListNode *FindNode(ListNode *hd, int x){
if(x<=0 || x>ListLen) return NULL;
for(int i=1;i<=x;i++){
hd = hd->next;
}
return hd;
}
三、数组模拟双向链表
#include <stdio.h>
#include <iostream>
using namespace std;
int a[100010][3],n,m,k,p,head=1;
//a[i][2]表示学号为i的同学右边同学的学号
//a[i][3]表示学号为i的同学左边同学的学号
int main(void){
a[1][1] = 1;
cin >> n;
for(int i=2;i<=n;i++){
cin >> k >> p;
a[i][1] = i;
if(p == 0){
a[a[k][3]][2] = i; a[i][2] = k;
a[i][3] = a[k][3]; a[k][3] = i;
if(k == head) head = i;
}
else{
a[a[k][2]][3] = i; a[i][3] = k;
a[i][2] = a[k][2]; a[k][2] = i;
}
}
cin >> m;
for(int i=1;i<=m;i++){
cin >> k;
if(a[k][1] != 0){
a[k][1] = 0;
a[a[k][3]][2] = a[k][2];
a[a[k][2]][3] = a[k][3];
n--;
if(k == head) head = a[k][2];
}
}
while(n--){
cout << a[head][1] << " ";
head = a[head][2];
}
return 0;
}