链表

优点:插入删除比顺序表快
缺点:不能随机访问

结构

typdef struct listNode_{
	DataType data;    //数据域
	listNode *next;    //指针域
}listNode,*linkedList;    //linkedList用于声明头指针
  • 首元节点:第一个存数据的节点
  • 头指针:指向链表第一个节点的指针
  • 为了使首元节点和其他节点的删除插入操作一致,在表头添加头节点,头节点的next指向首元节点,head指针指向头节点

初始化

申请一块头节点,头节点的指针域指向空,返回头节点地址

linkedList initialLinkedList(){
	listNode *head = new listNode;  
	if (!head) {  
	    cout << "申请失败" << endl;  
	    return nullptr;  
	}
	head->next = nullptr;  
	return head;
}

插入

头插法

插入节点newNode,更新newNode的指针域,再更新头节点head的指针域

linkedList head_insert(linkedList head, int key) {  
    listNode *newNode = new listNode;  
    newNode->data = key;  
    newNode->next = head->next;  
    head->next = newNode;  
    return head;  
}

尾插法

先通过遍历找到尾节点,再更新原尾节点的指针域

linkedList rear_insert(linkedList head, int key) {  
    listNode *newNode = new listNode;  
    newNode->data = key;  
    listNode *p = head;  
    while (p->next) {  
       p = p->next;  
    }  
    newNode->next = p->next;  
    p->next = newNode;  
    return head;  
}
  • 优化:用指针rear记录尾节点,每次尾插之后更新rear指针

查找

通过遍历查找

listNode *find(linkedList head, int key) {  
    listNode *p = head->next;  
    if (!p) {  
       cout << "链表为空" << endl;  
       return p;  
    }  
    while (p && p->data != key) {  //先判空再比较,反过来会非法访问
       p = p->next;  
    }  
    if (!p)cout << "没找到" << endl;  
    return p;  
}

删除

  • 将要删除的节点的前驱的指针域指向要删除节点的后继
  • 回收要删除的节点
linkedList Delete(linkedList head, int key) {  
    listNode *p = head->next;  
    while (p->next && p->next->data != key) {  
       p = p->next;  
    }  
    if (p->next == nullptr) {  
       cout << "未找到" << endl;  
       return head;  
    }  
    
    listNode *temp = p->next;  
    p->next = p->next->next;  
    delete temp;  
    temp=nullptr;    //防止temp成为野指针
    return head;  
}

双向链表与循环链表与单链表类似

双向链表

结构

struct listNode {  
    int data;  
    listNode *pre, *next;  
};

初始化

LinkedList initial() {  
    LinkedList head = new listNode;  
    head->next = head->pre = nullptr;  
    return head;  
}

插入

头插法

LinkedList head_insert(LinkedList head, int key) {  
    listNode *newNode = new listNode;  
    newNode->data = key;  
    newNode->next = head->next;  
    head->next = newNode;  
    newNode->pre = head;  
    if (newNode->next)  
       newNode->next->pre = newNode;  
    return head;  
}

尾插法

LinkedList rear_insert(LinkedList head, int key) {  
    listNode *newNode = new listNode;  
    newNode->data = key;  
    listNode *p = head;  
    while (p->next) {  
       p = p->next;  
    }  
    newNode->next = nullptr;  
    newNode->pre = p;  
    p->next = newNode;  
    return head;  
}

删除

LinkedList Delete(LinkedList head, int key) {  
    listNode *p = head->next;  
    while (p && p->data != key) {  
       p = p->next;  
    }  
    if (!p) {  
       cout << "未找到" << endl;  
       return head;  
    }  
    p->pre->next = p->next;  
    if (p->next)p->next->pre = p->pre;  
    delete p;  
    p = nullptr;  
    return head;  
}

循环链表

循环链表默认有头节点,循环链表的尾节点的next指针域指向头节点

  • 初始化循环链表时,头节点的指针域指向自己

链表逆转

双指针

  1. pre指针指向上一个节点,cur指向当前节点,用temp指向cur的下一个节点
  2. curnext指向pre
  3. pre指向cur,再cur指向temp
  4. cur为空退出循环
void reverseLinkedList(listNode *head){
	listNode *pre=nullptr;
	listNode *cur=head->next;
	listNode *tmep=nullptr;
	while(cur){
		temp=cur->next;
		cur->next=pre;
		pre=cur;
		cur=temp;
	}
	head->next=pre;
}

快慢指针

要找到链表中倒数第k个节点

  1. fast指针指向链表中第k+1个节点,slow指向链表中第1个节点
  2. fastslow同时往下遍历
  3. fast为空退出循环,此时slow为倒数第k个节点
listNode find(listNode *head){
	listNode *fast=head->next;
	listNode *slow=head->next;
	for(int i=0;i<k;i++){
		fast=fast->next;
		if(!fast){
			cout<<"error"<<endl;
			return nullptr;
		}
	}
	while(fast){
		fast=fast->next;
		slow=slow->next;
	}
	return slow;
}

静态链表

用数组存储,指针域存下一个节点的下标,下标0表示空

结构

struct listNode{
	DataType data;    //数据域
	int next;    //指针域
};

struct staticList{
	int capacity;    //数组长度-1
	int size;    //表中节点个数
	listNode *nodes;
	int first;    //第一个节点的下标
}

跳表

有序链表实现二分查找

  • 一个跳表有(logN)层链表,上一层链表节点数是下一层节点数的1/2
  • 最底层的是原始链表,包含所有数据
  • 每层链表都是有序的
  • 上层的节点的其中一个指针域指向下层相同值的节点
  • head->next指向最上层第一个节点
posted @ 2026-04-11 20:12  mofei1116  阅读(3)  评论(0)    收藏  举报