循环链表
如上所示,这里200,500都是地址,而1,2,3,4,5是数据,因此头节点是不存储数据的。
这里头节点不存储数据,不代表循环链表的头节点头都不存储数据,按照你自己的需求和喜好进行设计即可。
废话不多说,直接上干货
1. 循环链表的结构定义
typedef struct Node{
int data;
Node* next;
Node():data(0),next(this){};
Node(int x, Node *node):data(x),next(node){};
}*ListNode;
上述定义了循环链表结构,初始化只需要调用默认构造即可。
- 这里采用初始化列表的方式初始化Node,不仅仅是因为这样写简洁方便,而是这种方式在有些时候是比在函数体里面初始化更加的高效。
- 使用typedef的方式在下方定义的*ListNode是一个结构体类型而不是一个变量。
- this指针是一个指向自己的指针。
2. 建立一个线性链表
因为这里我们写了链表的一个有参构造,这样初始化链表就变得非常简单。
template<typename T>
void CreateList(ListNode &link_list, T arr, int len){
Node* p = link_list;
for(int i=0; i<len; i++){
p->next = new Node(arr[i], link_list);
p = p->next;
}
}
void ShowList(const ListNode &link_list){
Node* p = link_list->next;
while(p != link_list){
cout << p->data << "\t";
p = p->next;
}
cout << endl;
}
直接调用有参构造就可以了。
查找节点
查找节点又分按值查找和按位查找,具体代码如下所示
//按值查找节点
Node* FindValue(const ListNode &link_list, int val){
Node *p = link_list->next;
while(link_list != p){
if(p->data == val) return p;
p = p->next;
}
return NULL;
}
//按索引查找节点
Node* FindIndex(const ListNode &link_list, int index){
Node *p = link_list->next;
int count = 0;
while(link_list != p){
if(count == index) return p;
p = p->next;
count++;
}
return NULL;
}
修改节点
只需要判断什么时候转了一圈即可
void ChangeNode(ListNode &link_list,int index, int val){
int count = 0;
Node *p = link_list->next;
while(link_list != p){
if(count == index){
p->data = val;
return;
}
p = p->next;
count++;
}
cout<<"修改失败"<<endl;
}
插入节点
分为尾部插入(尾部添加)和中间插入(不包含尾部添加)
//尾部插入
void InsertRear(ListNode &link_list, int val){
Node *p = link_list;
while(link_list != p->next){
p = p->next;
}
p->next = new Node(val, link_list);
}
//中间插入
void InsertInside(ListNode &link_list,int index, int val){
int count = 0;
Node *p = link_list;
while(link_list != p->next){
if(count == index){
Node *temp = new Node(val, p->next);
p->next = temp;
return;
}
p = p->next;
count++;
}
cout<<"index超出索引"<<endl;
}
删除节点
因为节点是new出来的,注意注销即可。
void RemoveInside(ListNode &link_list, int index){
Node *p = link_list;
int count = 0;
while(link_list != p->next){
if(count == index){
Node* temp = p->next->next;
delete p->next;
p->next = temp;
return;
}
p = p->next;
count++;
}
cout << "index 超出索引" << endl;
}
总结
循环链表对比与单链表,它没有指针指向NULL,而是构成了一个圈,但是基本的增删改查相差不大,主要是结束循环的判断条件。
循环链表在某些调度问题上会用到。
对于链表操作,最关键的就是申明一个临时指针去访问链表,这样链表头节点的位置就不会因为增删改查操作而改变。
老规矩,有用,希望能送上你的二连,感谢!
附录
全部代码
#include<iostream>
#include<cstdlib>
#include<vector>
using namespace std;
typedef struct Node{
int data;
Node* next;
Node():data(0),next(this){};
Node(int x, Node *node):data(x),next(node){};
}*ListNode;
template<typename T>
void CreateList(ListNode &link_list, T arr, int len){
Node* p = link_list;
for(int i=0; i<len; i++){
p->next = new Node(arr[i], link_list);
p = p->next;
}
}
void ShowList(const ListNode &link_list){
Node* p = link_list->next;
while(p != link_list){
cout << p->data << "\t";
p = p->next;
}
cout << endl;
}
Node* FindValue(const ListNode &link_list, int val){
Node *p = link_list->next;
while(link_list != p){
if(p->data == val) return p;
p = p->next;
}
return NULL;
}
Node* FindIndex(const ListNode &link_list, int index){
Node *p = link_list->next;
int count = 0;
while(link_list != p){
if(count == index) return p;
p = p->next;
count++;
}
return NULL;
}
void ChangeNode(ListNode &link_list,int index, int val){
int count = 0;
Node *p = link_list->next;
while(link_list != p){
if(count == index){
p->data = val;
return;
}
p = p->next;
count++;
}
cout<<"修改失败"<<endl;
}
void InsertRear(ListNode &link_list, int val){
Node *p = link_list;
while(link_list != p->next){
p = p->next;
}
p->next = new Node(val, link_list);
}
void InsertInside(ListNode &link_list,int index, int val){
int count = 0;
Node *p = link_list;
while(link_list != p->next){
if(count == index){
Node *temp = new Node(val, p->next);
p->next = temp;
return;
}
p = p->next;
count++;
}
cout<<"index超出索引"<<endl;
}
void RemoveInside(ListNode &link_list, int index){
Node *p = link_list;
int count = 0;
while(link_list != p->next){
if(count == index){
Node* temp = p->next->next;
delete p->next;
p->next = temp;
return;
}
p = p->next;
count++;
}
cout << "index 超出索引" << endl;
}
int main(){
ListNode link_list = new Node();
vector<int> a = {1,2,3,4,5};
CreateList(link_list, a , a.size());
ShowList(link_list);
Node *temp = FindValue(link_list,5);
cout << temp->data << endl;
temp = FindValue(link_list,8);
if(temp == NULL) cout<<"找不到"<<endl;
temp = FindIndex(link_list,4);
if(temp == NULL) cout<<"找不到"<<endl;
else cout << temp->data << endl;
ChangeNode(link_list, 0, 100);
ShowList(link_list);
ChangeNode(link_list, 4, 100);
ShowList(link_list);
InsertInside(link_list,0, 1000);
ShowList(link_list);
InsertRear(link_list, 10000);
ShowList(link_list);
RemoveInside(link_list,0);
ShowList(link_list);
RemoveInside(link_list,5);
ShowList(link_list);
RemoveInside(link_list,5);
ShowList(link_list);
system("pause");
return 0;
}