循环链表是另一种形式的链式存储结构。它的特点是表中最后一个结点的指针域指向头结点,整个链表形成一个环。
结点类:
class Node
{
public:
int data; //数据域
Node *next; //指针域
};
结尾增加:
void append(Node **head, int data)
{
if(*head == nullptr)
{
*head = new Node;
(*head)->data = data;
(*head)->next = *head;
}
else
{
Node *tail;
//寻找尾节点
for(tail = *head; tail->next != *head; tail = tail->next);
Node *newNode;
newNode = new Node;
newNode->data = data;
newNode->next = *head; //新节点指向头节点
tail->next = newNode; //尾节点指向新节点
}
}
按下标插入:
// **head-头结点, index-将要插入的下标位置, data-数据域
void insert(Node **head, int index, int data)
{
//创建新结点
Node *newNode = new Node;
newNode->data = data;
//插入在头结点位置
if(index == 0)
{
//记录头结点
Node *tail = *head;
//循环到尾部, 如果位置超出链表的长度, 将插入队尾。
for(tail = *head; tail->next != *head; tail = tail->next);
//新头结点的指针域指向原头结点
newNode->next = *head;
//尾结点指针域与新头结点衔接
tail->next = newNode;
//*head要从函数中带出新头结点的位置
*head = newNode;
}
else
{
Node *pre = *head;
//找到前驱结点,要插入在当前index的下标,所以要index-1
for(int i = 0; i < index - 1; i++)
{
pre = pre->next;
}
newNode->next = pre->next;
pre->next = newNode;
}
}
按下标删除:
void remove(Node **head, int index)
{
if(*head == nullptr)
{
return;
}
if(index == 0)
{
Node *tail = *head;
//找到尾结点
for(tail = *head; tail->next != *head; tail = tail->next);
Node *del = *head;
*head = (*head)->next;
tail->next = *head;
delete del;
}
else
{
Node *pre = *head;
//找到前驱结点,要删除当前index的下标,所以要index-1
for(int i = 0; i < index - 1; i++)
{
if(pre->next == *head)
{
//前驱结点的下一个结点为head且仍进入了for循环,
//说明index大于链表长度,下标越界
cout << "index of range!" << endl;
return;
}
pre = pre->next;
}
//前驱结点指向要删除结点的后继结点,此时pre->next是要删除的结点
Node *del = pre->next;
pre->next = pre->next->next;
delete del;
}
}
遍历链表:
Node *mark = head;
while(head)
{
cout << head->data;
head = head->next;
if(mark == head)
{
break;
}
this_thread::sleep_for(chrono::milliseconds(100)); //休眠100毫秒,不需要可删除
}
相关链接:c++实现单链表头插、尾插、删除、遍历