这里头节点是不存储数据的,且单向链表的操作,双向链表都可以做到,这里讲一下双向链表的特点。
如果想看一些基础的增删改查工作,直接查看单链表即可
C++数据结构之单链表
废话不多说,直接上干货
//定义链表
typedef struct Node{
int data;//存放数据
Node* pre; //指向上一个节点
Node* next;//指向下一个节点
Node(): data(0),pre(NULL),next(NULL){};
Node(int x, Node* node): data(x),pre(node),next(NULL){};
Node(int x, Node* node, Node* node2): data(x),pre(node),next(node2){};
}*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], p); //每一步都设置前驱节点
p = p->next;
}
}
void ShowList(const ListNode &link_list){
Node* p = link_list->next;
if(NULL == p) return;
while(NULL != p->next){
cout << p->data << "\t";
p = p->next;
}
cout<<p->data << endl;
}
int main(void){
ListNode link_list = new Node();
vector<int> a = {1,2,3,4,5};
CreateList(link_list, a, a.size());
Node *p = link_list->next->next;
cout<<p->pre->data<<endl;
ShowList(link_list);
system("pause");
return 0;
}
直接调用有参构造就可以了。
增删改查操作,单链表能做的,双向链表也能做,不过有一些区别
//插入尾部节点
void InsertRear(ListNode &link_list, int val){
Node *p = link_list;
while(NULL != p->next){
p = p->next;
}
p->next = new Node(val, p);
}
//插入中间节点
void InsertInside(ListNode &link_list,int index, int val){
int count = 0;
Node *p = link_list;
while(NULL != p->next){
if(count == index){
Node *temp = new Node(val, p); //新节点的前驱指针指向p
temp->next = p->next; //新节点的后继指针指向后一个节点
p->next->pre = temp; //后继节点的前驱指针指向新节点
p->next = temp; //前驱节点的后继指针指向新节点
return;
}
p = p->next;
count++;
}
cout<<"插入失败"<<endl;
}
void RemoveRear(ListNode &link_list){
Node *p = link_list->next;
if(NULL == p){
cout << "链表为空" << endl;
return;
}else if(NULL == p->next){
delete p;
link_list->next = NULL;
}
while(NULL != p->next->next){
p = p->next;
}
delete p->next;
p->next = NULL;
}
void RemoveInside(ListNode &link_list, int index){
Node *p = link_list;
if(NULL == p->next){
cout << "链表为空" << endl;
return;
}
int count = 0;
while(NULL != p->next->next){
if(count == index){
Node* temp = p->next->next; //得到后继节点
temp->pre = p; //修改后继节点的前驱指针
delete p->next; //删除节点
p->next = temp; //修改前驱节点的后继指针
return;
}
p = p->next;
count++;
}
cout << "index 超出索引" << endl;
}
双向链表麻烦的地方就在于指针的指向操纵要更加的复杂一点,但是同样灵活性也更加的好一些。
Node* FindNode(const ListNode &link_list, int val){
Node *p = link_list->next;
while(NULL != p){
if(p->data == val) return p;
p = p->next;
}
return NULL;
}
这个和单链表是一样的
void ChangeNode(ListNode &link_list,int index, int val){
int count = 0;
Node *p = link_list->next;
if(NULL == p){
cout << "链表为空" << endl;
return;
}
while(NULL != p->next){
if(count == index){
p->data = val;
return;
}
p = p->next;
count++;
}
cout<<"修改失败"<<endl;
}
具体的问题需要具体的分析,目前还没遇到过什么问题使用双链表才是妙手的情况,所以这里暂时就介绍基础的操作。
老规矩,有用,希望能送上你的二连,感谢!
全部代码
#include
#include
#include
#include
#include
using namespace std;
//定义链表
typedef struct Node{
int data;//存放数据
Node* pre; //指向上一个节点
Node* next;//指向下一个节点
Node(): data(0),pre(NULL),next(NULL){};
Node(int x, Node* node): data(x),pre(node),next(NULL){};
Node(int x, Node* node, Node* node2): data(x),pre(node),next(node2){};
}*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], p);
p = p->next;
}
}
void ShowList(const ListNode &link_list){
Node* p = link_list->next;
if(NULL == p) return;
while(NULL != p->next){
cout << p->data << "\t";
p = p->next;
}
cout<<p->data << endl;
}
Node* FindNode(const ListNode &link_list, int val){
Node *p = link_list->next;
while(NULL != p){
if(p->data == val) return p;
p = p->next;
}
return NULL;
}
void InsertRear(ListNode &link_list, int val){
Node *p = link_list;
while(NULL != p->next){
p = p->next;
}
p->next = new Node(val, p);
}
void InsertInside(ListNode &link_list,int index, int val){
int count = 0;
Node *p = link_list;
while(NULL != p->next){
if(count == index){
Node *temp = new Node(val, p); //新节点的前驱指针指向p
temp->next = p->next; //新节点的后继指针指向后一个节点
p->next->pre = temp; //后继节点的前驱指针指向新节点
p->next = temp; //前驱节点的后继指针指向新节点
return;
}
p = p->next;
count++;
}
cout<<"插入失败"<<endl;
}
void ChangeNode(ListNode &link_list,int index, int val){
int count = 0;
Node *p = link_list->next;
if(NULL == p){
cout << "链表为空" << endl;
return;
}
while(NULL != p->next){
if(count == index){
p->data = val;
return;
}
p = p->next;
count++;
}
cout<<"修改失败"<<endl;
}
void RemoveRear(ListNode &link_list){
Node *p = link_list->next;
if(NULL == p){
cout << "链表为空" << endl;
return;
}else if(NULL == p->next){
delete p;
link_list->next = NULL;
}
while(NULL != p->next->next){
p = p->next;
}
delete p->next;
p->next = NULL;
}
void RemoveInside(ListNode &link_list, int index){
Node *p = link_list;
if(NULL == p->next){
cout << "链表为空" << endl;
return;
}
int count = 0;
while(NULL != p->next->next){
if(count == index){
Node* temp = p->next->next; //得到后继节点
temp->pre = p; //修改后继节点的前驱指针
delete p->next; //删除节点
p->next = temp; //修改前驱节点的后继指针
return;
}
p = p->next;
count++;
}
cout << "index 超出索引" << endl;
}
int main(void){
ListNode link_list = new Node();
vector<int> a = {1,2,3,4,5};
CreateList(link_list, a, a.size());
Node *p = link_list->next->next;
cout<<p->pre->data<<endl;
ShowList(link_list);
InsertInside(link_list, 0, 100);
ShowList(link_list);
InsertInside(link_list, 6, 100);
ShowList(link_list);
InsertRear(link_list, 100);
ShowList(link_list);
InsertInside(link_list, 2, 100);
ShowList(link_list);
RemoveRear(link_list);
ShowList(link_list);
RemoveInside(link_list, 6);
ShowList(link_list);
Node *temp = FindNode(link_list, 100);
cout << temp->data << endl;
ChangeNode(link_list, 0, 1000);
ShowList(link_list);
system("pause");
return 0;
}