关于单向链表
单向链表是链表最常用的一种,一个列表节点有两个字段,即数据域和指针域。在单向链表中,指向第一个节点的节点称为"头结点",最后一个节点的指针域设为null。
如图即是{1,3,1,4,5,2,1}存在在单向链表的示意图,头节点数据域为null,指向首节点(数据域为1),首节点指向下一个节点,一直到最后一个节点,指向null。1部分是3部分的前驱节点,3部分是1部分的后驱节点。
1.已知列表的每一个节点有数据域和指针域组成,故定义一个节点结构体ListNode:
c
struct ListNode{
eleType data;
ListNode *next;
ListNode(eleType ele) : data(ele), next(nullptr) {}
};
解释: data表示数据域,*next表示下一个节点(后继节点)。ListNode(eleType ele) : data(ele), next(nullptr) {}
构造函数,在声明节点对象的时候,将ele赋值给data,next节点设置为空。
2.接下来建立一个链表类LinkedList:
c
class LinkedList{
private:
ListNode *head;
int size;
public:
LinkedList() : head(nullptr), size(0) {}
~LinkedList();
//增删改查
void insertToIndex(int index,eleType element); //增
void removeByIndex(int index); //删
ListNode* getListNodeByIndex(int index); //改
void updateListNodeByIndex(int index,eleType value); //差
void printList(); //打印
};
解释: 该类有两个私有成员,*head表示头节点,size表示链表长度,在构造函数中分别初始化为null和0,表示是一个空表。定义了析构函数,在后面实现。另声明了该类的增删改查函数。
3.实现析构函数,在销毁链表时调用:
c
/*定义一个游标节点,从头节点出发,遍历,赋值给tmp,执行删除*/
LinkedList::~LinkedList(){
ListNode *curr = head;
while (curr != nullptr) {
ListNode *tmp = curr;
curr = curr->next;
delete tmp;
}
}
4.插入函数实现:
c
void LinkedList::insertToIndex(int index, eleType element){
if(index < 0 || index > size)
throw out_of_range("Invalid position");
ListNode *newNode = new ListNode(element);
if(index == 0){
newNode->next = head;
head = newNode;
}else{
ListNode *curr = head;
for(int i = 0; i < index - 1; ++ i){
curr = curr->next;
}
newNode->next = curr->next;
curr->next = newNode;
}
++ size;
}
解释: 传入index以及要插入的元素,首先进行下表越界判断,抛出异常。之后通过ListNode创建一个新节点,如果要插入位置为头节点,就让新节点指向头节点,将头节点赋值给新节点。如果插入位置不是头节点,则建立一个游标节点curr,循环遍历至要插入的位置的前一个节点,之后把新节点指向这个位置的后一个节点,再让这个位置的后继节点等于新节点。最后size加一。
5.删除函数实现
c
void LinkedList::removeByIndex(int index){
if(index < 0 || index > size)
throw out_of_range("Invalid position");
ListNode *curr = head;
for(int i = 0; i < index - 1; ++ i){
curr = curr->next;
}
ListNode *temp = curr->next;
curr->next = temp->next;
delete temp;
}
解释: 传入index表示要删除节点的位置,首先进行下表合法校验。之后同样建立游标节点,遍历至要删除位置的前一个节点,然后建立一个临时节点保存要删除的节点,在让curr的后继节点指向tmp的后继节点,之后删除tmp。
5.查找函数实现
c
ListNode* LinkedList::getListNodeByIndex(int index){
if(index < 0 || index > size)
throw out_of_range("Invalid position");
ListNode *curr = head;
for(int i = 0; i < index;i++){
curr = curr->next;
}
return curr;
}
解释 该函数返回的是一个节点类型,首先进行下表判断,之后遍历至要返回的位置,返回该节点即可。
6.修改函数实现
c
void LinkedList::updateListNodeByIndex(int index,eleType value){
if(index < 0 || index > size)
throw out_of_range("Invalid position");
getListNodeByIndex(index)->data = value;
};
解释该函数返回值为空,直接调用查找函数找到对应节点,之后修改其指针域为对应值即可。
主函数测试
c
int main(){
LinkedList list;
list.insertToIndex(0, 33);
list.insertToIndex(1, 33);
list.insertToIndex(2, 33);
list.updateListNodeByIndex(2, 66);
//list.removeByIndex(0);
list.printList();
cout<<list.getListNodeByIndex(0)->data;
}
/*
结果:
33 33 66
---------------------
33
*/
完整程序
c
#include <iostream>
#include<stdexcept>
using namespace std;
#define eleType int
struct ListNode{
eleType data;
ListNode *next;
ListNode(eleType ele) : data(ele), next(nullptr) {}
};
class LinkedList{
private:
ListNode *head;
int size;
public:
LinkedList() : head(nullptr), size(0) {}
~LinkedList();
void insertToIndex(int index,eleType element);
void removeByIndex(int index);
ListNode* getListNodeByIndex(int index);
void updateListNodeByIndex(int index,eleType value);
void printList();
};
LinkedList::~LinkedList(){
ListNode *curr = head;
while (curr != nullptr) {
ListNode *tmp = curr;
curr = curr->next;
delete tmp;
}
}
void LinkedList::insertToIndex(int index, eleType element){
if(index < 0 || index > size)
throw out_of_range("Invalid position");
ListNode *newNode = new ListNode(element);
if(index == 0){
newNode->next = head;
head = newNode;
}else{
ListNode *curr = head;
for(int i = 0; i < index - 1; ++ i){
curr = curr->next;
}
newNode->next = curr->next;
curr->next = newNode;
}
++ size;
}
void LinkedList::removeByIndex(int index){
if(index < 0 || index > size)
throw out_of_range("Invalid position");
ListNode *curr = head;
for(int i = 0; i < index - 1; ++ i){
curr = curr->next;
}
ListNode *temp = curr->next;
curr->next = temp->next;
delete temp;
}
ListNode* LinkedList::getListNodeByIndex(int index){
if(index < 0 || index > size)
throw out_of_range("Invalid position");
ListNode *curr = head;
for(int i = 0; i < index;i++){
curr = curr->next;
}
return curr;
}
void LinkedList::updateListNodeByIndex(int index,eleType value){
if(index < 0 || index > size)
throw out_of_range("Invalid position");
getListNodeByIndex(index)->data = value;
};
void LinkedList::printList(){
ListNode *curr = head;
while (curr != nullptr) {
cout<<curr->data<<' ';
curr = curr->next;
}
cout<<"\n---------------------\n";
}
int main(){
LinkedList list;
list.insertToIndex(0, 33);
list.insertToIndex(1, 33);
list.insertToIndex(2, 33);
list.updateListNodeByIndex(2, 66);
//list.removeByIndex(0);
list.printList();
cout<<list.getListNodeByIndex(0)->data;
}