C++循环链表
单向循环链表和单向链表的区别:
(1)单向链表为头指针,循环链表为尾指针,头指针指向头结点,尾指针指向终端结点;
(2)为统一方便操作,单向链表设置头结点,单向循环链表设置头结点和尾结点;
(3)设置尾结点后,尾指针指向尾结点,插入,删除等操作不用移动尾指针。
在单向链表中,链表最后一个结点的next指针指向NULL,而所谓的循环链表就是将最后一个结点本来指向空的改变其指针指向从而指向首结点(注意不是头结点,头结点是方便链表操作而存在的结构体,循环链表是一种特殊的单向链表)循环链表可以继承自单向链表。
循环链表主要实现难点:
(1)插入数据的位置为0时,头结点和尾结点的next指针均指向新结点。
(2)删除位置为0的结点时,头结点和尾结点的next指针都指向为位置为1的结点,然后安全删除位置为0的结点。
//cyclelist.h 定义链表
#include <iostream>
using namespace std;
class ListNode{
public:
ListNode(){
};
ListNode(int e,ListNode* p=NULL):data(e),next(p){
}
~ListNode(){
}
public:
int data;
ListNode* next;
};
class CycleList{
public:
CycleList();
~CycleList();
//判断列表是否为空
bool isEmpty();
//头部添加元素
void appendHead(int element);
//尾部添加元素
void appendTail(int element);
//获取元素位置
int getElemPos(int element);
//获取指定位置的ListNode指针
ListNode* getElement(int pos);
//向指定位置插入元素
void InsertElem(int pos,int element);
//s删除首个与element相同的元素
void deleteElem(int element);
//移除pos位置上的元素
void removeElem(int pos);
//清空列表
void clear();
//打印列表
void printList();
int getLength(){
return m_length;
}
private:
ListNode* head;
ListNode* rear;
int m_length;
};
//cyclelist.cpp 实现链表的操作
#include "cyclelist.h"
//循环链表的构造函数,构造表头
CycleList::CycleList():m_length(0){
head=new ListNode;
head->next=head;
head->data=0;
rear=NULL;
}
//循环链表析构函数,将链表清空
CycleList::~CycleList(){
if(head){
ListNode* p=head->next;
while(p!=rear){
head->next=p->next;
delete p;
p=head->next;
}
delete head;
head=NULL;
delete rear;
rear=NULL;
}
}
//判断链表是否为空
bool CycleList::isEmpty(){
if(m_length>0)
return false;
return true;
}
//头部添加元素
void CycleList::appendHead(int element){
if(head==head->next){
//空表
ListNode* node=new ListNode(element);
head->next=node;
node->next=head;
rear=node;
}else{
ListNode* node=new ListNode(element,head->next);
rear->next=node;
head->next=node;
}
++m_length;
}
//在链表位插入元素
void CycleList::appendTail(int element){
if(head==head->next){
//判断空表
ListNode* node=new ListNode(element);
head->next=node;
rear=node;
}else{
ListNode* node=new ListNode(element,head->next);
rear->next=node;
rear=node;
node->next=head->next;
}
++m_length;
}
//获取元素位置
int CycleList::getElemPos(int element){
if(head==head->next){
return -1;
}
ListNode* node=head->next;
for(int i=0;node!=rear&&i<m_length;++i,node=node->next){ //寻找相同元素的位置
if(element==node->data)
return i;
}
if(rear->data==element){
return m_length-1;
}
return -1;
}
//获取指定位置的ListNode指针
ListNode* CycleList::getElement(int pos){
if(pos<0||pos>=m_length||head==head->next)
return NULL;
ListNode* node=head->next;
for(int i=0;i<pos;++i,node=node->next){ //寻找当前结点的位置
;
}
return node;
}
//输入插入位置并在该位置后插入元素
void CycleList::InsertElem(int pos,int element){
if(pos<0||pos>m_length)
return;
if(pos==0){ //在头结点插入
head->next=new ListNode(element,head->next); //新建一个结点
if(m_length==0){
rear=head->next;
}
rear->next=head->next; //并将尾结点指向头结点
}else if(pos==m_length){ //在尾部插入
ListNode* node=new ListNode(element);
if(m_length==0){
head->next=node;
node->next=node;
rear=node;
}else{
rear->next=node;
rear=node;
node->next=head->next;
}
}else{ //在中间插入元素
ListNode* node=head->next;
for(int i=0;i<pos-1;++i,node=node->next){ //寻找插入位置的前一个结点
;
}
ListNode* newNode=new ListNode(element,node->next); //将新结点指向下一个位置
node->next=newNode; //前一个结点指向新结点
}
++m_length;
}
//删除第一个与element相等的元素
void CycleList::deleteElem(int element){
if(head==head->next)
return;
ListNode* node=head->next;
ListNode* helpNode=head;
int pos=-1;
//遍历整个链表
while(node!=rear){ //寻找pos所在的位置
++pos;
if(node->data==element){
break;
}
node=node->next;
helpNode=helpNode->next;
}
if(m_length==1){ //只有一个结点时候的删除
if(rear->data==element){
head->next=head;
rear=NULL;
delete node;
node=NULL;
}
}
else{
if(node!=rear){
helpNode->next=node->next; //将需要删除的结点的指针赋给help结点
if(pos==0){
rear->next=node->next; //删除头结点
}
delete node;
node=NULL;
}else{
if(rear->data==element){ //删除尾结点
helpNode->next=node->next;
delete node;
node=NULL;
rear=helpNode;
}
}
}
--m_length;
}
//移除pos的元素
void CycleList::removeElem(int pos){
if(pos<0||pos>=m_length||head==head->next) //判断是否超出链表的长度
return;
ListNode* node=head->next;
if(m_length==1){ //判断是非只有一个结点并删除当前结点
delete node;
node=NULL;
head->next=head;
rear=NULL;
}else{
if(pos==0){ //判断输入的位置
ListNode* p=head->next->next; //将p指向需要移除的下一个位置
head->next=p;
rear->next=p;
delete node;
node=NULL;
}else if(pos==m_length-1){ //移除最后一个元素
for(int i=0;i<pos-1;i++){ //寻找最后一个元素
node=node->next;
}
delete rear; //删除尾元素,并将
rear=node;
node->next=head->next;
}else{
for(int i=0;i<pos-1;i++){
node=node->next;
}
ListNode* temp=node->next;
node->next=temp->next;
delete temp;
temp=NULL;
}
}
--m_length;
}
//清空链表
void CycleList::clear(){
ListNode* node=head->next; //定义表头
while(node!=rear){
head->next=node->next; //改变指针指向位置,使得指针指向下一个结点
delete node;
node=head->next; //将第一个结点定义为node
}
head->next=NULL; //将表头置为NULL
delete rear;
rear=NULL;
m_length=0;
}
//遍历链表
void CycleList::printList(){
cout<<"PrintList: "<<endl;
if(head!=head->next){ //链表是否为空
ListNode* p=head->next;
while(p){
cout<<p->data<<" "; //输入当前值,同时p向后移动一位
p=p->next;
if(p==head->next){ //查看p是否已经遍历完
break;
}
}
}
cout<<endl;
}
//测试链表
#include <iostream>
#include "cyclelist.h"
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int main(int argc, char** argv) {
CycleList testList;
for (int i = 0; i < 7; ++i)
{
testList.appendHead(i);
testList.appendTail(i);
}
testList.printList();
cout << "GetElemPos(6): " << testList.getElemPos(6) << endl;
cout << "GetElemPos(5): " << testList.getElemPos(5) << endl;
cout << "GetElemPos(0): " << testList.getElemPos(0) << endl;
cout << "GetElement(0): " << testList.getElement(0)->data << endl;
cout << "GetElement(13): " << testList.getElement(13)->data << endl;
cout << "GetElement(7): " << testList.getElement(7)->data << endl;
testList.removeElem(0);
testList.printList();
testList.removeElem(12);
testList.printList();
testList.removeElem(7);
testList.printList();
testList.deleteElem(5);
testList.printList();
testList.deleteElem(5);
testList.printList();
testList.deleteElem(0);
testList.printList();
CycleList testList2;
testList2.appendHead(2);
testList2.appendHead(1);
testList2.removeElem(1);
testList2.printList();
CycleList testList3;
testList3.appendHead(1);
testList3.deleteElem(1);
testList3.printList();
testList3.InsertElem(0, 3);
testList3.InsertElem(0, 2);
testList3.InsertElem(0, 1);
testList3.InsertElem(3, 3);
testList3.InsertElem(4, 2);
testList3.InsertElem(5, 1);
testList3.printList();
CycleList testList4;
testList4.InsertElem(0,1);
testList4.InsertElem(1,2);
testList4.InsertElem(1, 3);
testList4.InsertElem(3, 4);
testList4.printList();
testList.clear();
testList.printList();
return 0;
}
结果如下:
注意:(1)单向循环链表销毁时,需要将头结点和尾结点删除;(2)单向循环链表插入,删除,遍历,清空链表时,条件从头结点或第一节点始,判断指针是否达到尾结点;(3)清空链表时,最后将头结点指向尾结点;(4)销毁链表时,条件从头结点始,判断条件为指针是否到达头结点,最后将指针置空。