链表总结 Apare_xzc

链表总结

定义:

        链表是由若干个结点组成的,内存可以不连续。一般定义数据域和指针域,一般链表的结点我们可以用结构体定义
        由于链表的内存不连续,所以不支持随机访问(redis的跳表可以支持),但是插入和删除复杂度为O(1)

//单链表结点
struct ListNode{
	int val;
	struct ListNode * next;
	ListNode(int v):val(v),next(nullptr){}
	ListNode():next(nullptr){}
};
//树的结点
struct TreeNode{
	int val;
	struct TreeNode * left;
	struct TreeNode * right;
	//struct TreeNode * father;
	TreeNode(int v):val(v),left(nullptr),right(nullptr){}
};
//双向链表的结点
struct TwoWayListNode{
	int val;
	struct TwoWayListNode * pre,*next;
	TwoWayListNode(int v):val(v),pre(nullptr),next(nullptr){}
};

链表的分类

  1. 按照结构,可以分为单链表、双向链表、双向循环链表…
  2. 按照是否有序,可以分为有序链表和无序链表,有序链表再插入结点时要保证有序
  3. 按照是否由头节点,可以分为有头结点的链表、无头结点的链表

链表的基本操作

  1. 插入结点(在头部插入,在尾部插入,在中间插入)
  2. 删除一个结点(删除第K个,删除倒数第K个,删除有序链表的重复结点)
  3. 反转链表(递归,非递归,K个一组反转…)
  4. 链表排序(插入排序,归并排序)

我们可以参考STL的list,底层是双向(循环)链表实现的,看看list中是如何定义的。我们先看一个试验:

#include 
using namespace std;
int main(void) {
	list<int> List;
	List.push_back(100);
	List.push_back(200);
	List.push_back(300);
	auto it = List.begin();
	for(;it!=List.end();++it)
		cout<<*it<<" "; cout<<endl;
	cout<<*it<<endl;//输出end() 
	++it;
	cout<<*it<<endl; //输出end()的下一个
	it = List.begin();
	cout<<*(--it)<<endl;
	cout<<*(--it)<<endl; 
	
	return 0;
}

100 200 300
1
100
1
300

我们发现list的结构是一个循环链表,链表最后一个数据结点后是一个尾结点,end()指向这个尾结点,然后尾结点的next是链表的第一个数据元素。如下图
链表总结 Apare_xzc_第1张图片
我们可以看一下list给我们调用的常用的函数接口有哪些:

  • push_front(node):从链表头部插入一个结点
  • push_back(node):从链表尾部插入一个结点
  • pop_front():删除链表的首部元素
  • pop_back():删除链表的尾部元素
  • front():返回第一个元素
  • back(): 返回最后一个元素
  • size():返回容器中元素的个数
  • empty():返回容器是否为空
  • insert(iter,node):在迭代器iter指向的结点之前插入一个值为node的结点
  • erase(iter):删除迭代器指向的元素
  • erase(it1,it2):删除[it1,it2)这个区间的所有元素
  • remove(node):删出value等于node的所有结点
  • reverse(List.begin(),List.end()): 反转链表
  • sort(List.begin(),List.end()):链表排序(用非递归的归并排序实现)

一下是我写LRU算法中手写的双向链表List,实现了push_front(), pop_back(),erase(),设置了头结点head和尾结点tail,这样更方便写。


struct ListNode{
	int key,val;//数据部分 
	struct ListNode * next;
	struct ListNode * pre;
	ListNode(int key=0,int val=0):key(key),val(val),next(nullptr),pre(nullptr){}
};
struct List{
	int size;
	ListNode * head;
	ListNode * tail;
	List() {
		size = 0; 
		head = new ListNode();
		tail = new ListNode();
		head->next = tail;
		tail->pre = head;
	} 
	~List() {
		ListNode * p = head,*t;
		while(p) {
			t = p->next;
			delete p;
			p = t;
		}
	}
	ListNode * push_front(int key,int val) {
		++size;
		ListNode * t = new ListNode(key,val);
		ListNode * p = head->next;
		head->next = t;
		t->next = p;
		t->pre = head;
		p->pre = t;
		return t;
	}
	void push_front(ListNode * p) {
		++size;
		ListNode * t = head->next;
		head->next = p;
		p->next = t;
		t->pre = p;
		p->pre = head;
	}
	int pop_back() {
		--size;
		ListNode * p = tail->pre;
		ListNode * t = p->pre; 
		t->next = tail;
		tail->pre = t;
		int k = p->key;
		delete p; 
		return k;
	}
	void erase(ListNode * p) {
		--size;
		ListNode * pp = p->pre;
		ListNode * pn = p->next;
		pp->next = pn;
		pn->pre = pp;
	}
	void toHead(ListNode *p) { //把某个结点移动到链表首部 
		erase(p);
		push_front(p);
	}
}; 

我们可以拓展一下,看一看操作单链表有关的问题

  1. 单链表插入排序:
ListNode * Insertin_Sort(ListNode * head) {
	if(!head||(head&&!head->next)) return head; //一个结点不需要排序 
	ListNode * hair = new ListNode(0);
	hair->next = head;
	ListNode * p = head;
	while(p->next) {
		ListNode * q = p->next;
		if(q->val>=p->val) {
			p = p->next; 
			continue;//这个是有序的,不用排 
		}
		p->next = q->next;
		ListNode * t = hair;
		while(t->next->val <= q->val) t = t->next;
		q->next = t->next;
		t->next = q;
	} 
	head = hair->next;
	delete hair;	
	return head; 
}
  1. 单链表归并排序
ListNode * MergeSort(ListNode * head) {
	if(!head||(head&&!head->next)) return head; 
	ListNode * fast = head;
	ListNode * slow = head;
	while(fast->next&&fast->next->next) { //用快慢指针找到中点
		fast = fast->next->next;
		slow = slow->next;
	}
	ListNode * pR = MergeSort(slow->next);
	slow->next = nullptr;
	ListNode * pL = MergeSort(head);
	ListNode *  hair = new ListNode(0);
	ListNode * p = hair;
	while(pL||pR) {
		if(!pR||(pL&&pL->val<=pR->val)) {
			p->next = pL; pL = pL->next; p = p->next;
		} else {
			p->next = pR; pR = pR->next; p = p->next;	
		}
	}
	head = hair->next;
	delete hair;
	return head;
}
  1. 递归反转链表
ListNode * ReverseList(ListNode * Head) {
	if(!Head||(Head&&!Head->next)) return Head;
	ListNode * p = ReverseList(Head->next);
	Head->next->next = Head;
	Head->next = nullptr;
	return p;
}
  1. 非递归反转链表
ListNode * ReverseList2(ListNode * Head) {
	if(!Head||(Head&&!Head->next)) return Head;
	ListNode * tail = Head;
	while(tail->next) tail = tail->next;
	ListNode * last = tail->next; //nullptr
	ListNode * p = Head;
	while(last!=tail) {
		ListNode * nex = p->next;
		p->next = last;
		last = p;
		p = nex;
	}
	return tail;
}
  1. 删除单链表第K个结点,返回删除后的头节点,如果越界了,就不删除
ListNode * removeKth(ListNode * head,int k) { //删除第K个结点 
	if(k<=0) return head;
	ListNode * hair = new ListNode(0);
	hair->next = head;
	ListNode * p = hair;
	for(int i=1;i<k;++i) {
		p = p->next;
		if(!p->next) {
			delete hair;
			return head;
		}
	}	
	ListNode * q = p->next;
	p->next = q->next;
	delete q;
	head = hair->next;
	delete hair;
	return head;
}
  1. 删除单链表倒数第K个结点
ListNode * removeRKth(ListNode * head,int k) {
   if(k<=0) return head;
   ListNode * hair = new ListNode(0);
   hair->next = head;
   ListNode *p = hair, *q = hair;
   for(int i=1;i<=k;++i) {
   	p = p->next;
   	if(!p) {
   		delete hair;
   		return head;
   	}
   }
   while(p->next) {
   	p = p->next;
   	q = q->next;
   }
   p = q->next;
   q->next = p->next;
   delete p;
   head = hair->next;
   delete hair;
   return head;
}
  1. K个一组反转链表
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
 class Solution {
public:
    // 翻转一个子链表,并且返回新的头与尾
	pair<ListNode*,ListNode*> RevLinkList(ListNode * head,ListNode * tail) {
		ListNode * last = tail->next;
		ListNode * p = head;
		while(last!=tail) {
			ListNode * nex = p->next;
			p->next = last;
			last = p;
			p = nex;
		}
		return {tail,head};
	} 

    ListNode* reverseKGroup(ListNode* head, int k) {
    	ListNode * hair = new ListNode(0);
    	hair->next = head;
    	ListNode * pre = hair;
    	while(head) {
    		ListNode * tail = pre;
    		for(int i=0;i<k;++i) {
    			tail = tail->next;
    			if(!tail) return hair->next; //后面的链表长度不足K 
			}
			ListNode * nex = tail->next;
			pair<ListNode*,ListNode*> res = RevLinkList(head,tail);
			head = res.first;
			tail = res.second;
			
			tail->next = nex;
			pre->next = head;
			pre = tail;
			head = tail->next; 
		}
		return hair->next;
    }
};
 

自己封装的链表类

#include 
using namespace std; 
单链表结点
struct ListNode{
	int val;
	struct ListNode * next;
	ListNode(int v):val(v),next(nullptr){}
	ListNode():next(nullptr){}
};
struct LinkList{
	ListNode * head;
	int size;
	LinkList(); 
	void push_back(int);	
	void push_front(int); 
	void insertKth(int k,int v); //将结点v插入到链表第K个结点之前 
	bool removeKth(int k); //删除第K个结点 
	void show(); //按照[1,2,5]格式从到尾输出链表元素 
	bool removeRKth(int k); //删除倒数第K个结点	
	void destroy(); //删除链表,释放内存 
	~LinkList(); //析构函数 
	static ListNode * MergeSort(ListNode * head);//将单链表归并排序 
	void Merge_Sort(); //归并排序 
	static ListNode * ReverseList(ListNode * Head); //递归反转单链表 
	static ListNode * ReverseList2(ListNode * Head); //非递归反转单链表 
	void Reverse(); //反转链表 
	void Insertin_Sort(); //插入排序 
}; 
LinkList::LinkList() { //无参构造函数 
	size = 0;
	head = nullptr;
}
void LinkList::push_back(int v) {
	++size;
	ListNode * t = new ListNode(v);
	if(!head) {
		head = t;
		return;
	}
	ListNode * p = head;
	while(p->next) {
		p = p->next;
	}
	p->next = t;
}
void LinkList::push_front(int v) {
	++size;
	ListNode * t = new ListNode(v);
	if(!head) {
		head = t;
		return;
	}
	else {
		t->next = head->next;
		head->next = t;
	}
}
void LinkList::insertKth(int k,int v) { //将结点v插入到链表第K个结点之前 
	++size;
	ListNode * t = new ListNode(v);
	assert(k>0&&k<=size);
	if(k==1) {
		t->next = head->next;
		head = t; 
	} else {
		ListNode * p = head;
		for(int i=1;i<k;++i) p = p->next;
		t->next = p->next;
		p->next = t;
	}
}
bool LinkList::removeKth(int k) { //删除第K个结点 
	if(k<=0||k>size) return false;
	if(k==1) {
		ListNode * p = head->next;
		delete head;
		head = p;
	} else {
		ListNode * p = head;
		for(int i=2;i<k;++i) p = p->next;
		ListNode * q = p->next;
		p->next = q->next;
		delete q; 
	}
	return true;
}
void LinkList::show() {
	if(!head) puts("[]");
	else {
		printf("[%d",head->val);
		ListNode * p = head->next;
		while(p) {
			printf(" -> %d",p->val);
			p = p->next;
		}
		printf("]\n");
	}
}
bool LinkList::removeRKth(int k) { //删除倒数第K个结点 
	if(k<=0||k>size) return false;
	assert(k>0&&k<=size); 
	ListNode * hair = new ListNode(0);
	hair->next = head;
	ListNode * p = hair,*q=hair;
	for(int i=1;i<=k;++i) {
		assert(p);
		p = p->next;
	} 
	while(p->next) {
		p = p->next;
		q = q->next;
	} 
	p = q->next;
	q->next = p->next;
	delete p;
	head = hair->next;
	delete hair;
	return true;
}
void LinkList::destroy() { //删除链表,释放内存 
	while(head) {
		ListNode * nex = head->next;
		delete head;
		head = nex;
	}	
}
LinkList:: ~LinkList() {
	destroy();
}
ListNode * LinkList::MergeSort(ListNode * head) {
	if(!head||(head&&!head->next)) return head; 
	ListNode * fast = head;
	ListNode * slow = head;
	while(fast->next&&fast->next->next) {
		fast = fast->next->next;
		slow = slow->next;
	}
	ListNode * pR = MergeSort(slow->next);
	slow->next = nullptr;
	ListNode * pL = MergeSort(head);
	ListNode *  hair = new ListNode(0);
	ListNode * p = hair;
	while(pL||pR) {
		if(!pR||(pL&&pL->val<=pR->val)) {
			p->next = pL; pL = pL->next; p = p->next;
		} else {
			p->next = pR; pR = pR->next; p = p->next;	
		}
	}
	p = hair->next;
	delete hair;
	return p;
}
void LinkList::Merge_Sort() {
	head = LinkList::MergeSort(head);
}
ListNode * LinkList::ReverseList(ListNode * Head) {
	if(!Head||(Head&&!Head->next)) return Head;
	ListNode * p = ReverseList(Head->next);
	Head->next->next = Head;
	Head->next = nullptr;
	return p;
}
ListNode * LinkList::ReverseList2(ListNode * Head) {
	if(!Head||(Head&&!Head->next)) return Head;
	ListNode * tail = Head;
	while(tail->next) tail = tail->next;
	ListNode * last = tail->next; //nullptr
	ListNode * p = Head;
	while(last!=tail) {
		ListNode * nex = p->next;
		p->next = last;
		last = p;
		p = nex;
	}
	return tail;
}
void LinkList::Reverse() {
	head = LinkList::ReverseList2(head);
} 
void LinkList::Insertin_Sort() {
	if(!head||(head&&!head->next)) return; //一个结点不需要排序 
	ListNode * hair = new ListNode(0);
	hair->next = head;
	ListNode * p = head;
	while(p->next) {
		ListNode * q = p->next;
		if(q->val>=p->val) {
			p = p->next; 
			continue;//这个是有序的,不用排 
		}
		p->next = q->next;
		ListNode * t = hair;
		while(t->next->val <= q->val) t = t->next;
		q->next = t->next;
		t->next = q;
	} 
	head = hair->next;
	delete hair;	 
}
	
	
	
	
	



int main(void) {
	LinkList List;
	List.push_back(10);
	List.push_back(20);
	List.push_back(1);
	List.push_back(5);
	List.push_back(7);
	List.push_back(100);
	List.push_back(0);
	List.push_back(1);
	List.show(); 
	List.Reverse();
	List.show();
//	List.Insertin_Sort();
	List.Merge_Sort();
	List.show();
	return 0; 
	List.removeKth(1);
	List.show();
	 
	List.removeKth(3);
	List.show();
	List.removeRKth(1);
	List.show();
	List.removeRKth(5);
	List.show();
	List.removeRKth(4);
	List.show();
	List.Reverse();
	List.show();
	return 0;
}

2020.9.7
0:17


你可能感兴趣的:(数据结构,学习笔记,链表)