今天总结循环单链表
什么是单循环链表?
单链表终端结点的指针域是指向空的,如果将其指向头结点,这样就形成了一个环,那么这种首尾相接的环就够成了单循环链表.
单链表中我们都是用头指针来表示的,但是在单循环链表里,用尾指针(指向最后一个节点)。为什么要这样,因为如果用头指针,那么当查找最后一个元素的时候,就要循环遍历,时间复杂度为O(n),如果用尾指针,时间复杂度为O(1),而因为是循环的,所以头指针很容易表示出来即rear->next,时间复杂度也是O(1)
单循环链表中需要注意两点:
- 头指针使用rear->next表示的
- 判断某结点是否为尾结点条件是:rear->next==rear 而不是单链表中的p->next==NULL
图示(百度图片截取):
心得:在写链表这块的时候,由于指针有时会被绕,但我发现,一定要记住指针存放的就是地址,而这个地址通常表示的是一个结点。比如rear->next 代表的是头指针,而头指针里存放的地址是头结点的,也就是指向头结点,其实就代表了是头结点。指针这块需要好好的理解,揣摩,我是认为宁可慢一点,想明白了,也比快了,糊里糊涂的效果更好。
具体代码实现:
<span style="font-family:Courier New;font-size:14px;">#include <iostream> using namespace std; template <class T> struct Node{ T data; struct Node<T> *next; //指针域 }; template <class T> class CLinkList { public: //初始化空的循环单链表 CLinkList() { rear = new Node<T>; rear->next = rear; } CLinkList(T a[],int n); //初始化一个链表 ~CLinkList(); //析构函数 int GetLength(); //获取单链表的长度 T Get(int i); //获取线性表第i个位置上的元素 int Locate(T x); //查找线性表中值为x的元素 返回其位置 void Insert(int i,T x); //将元素x插入到位置i上 T Delete(int i); //删除位置i上的元素 并将删除元素返回 void PrintLinkList(); //循环遍历循环单链表中的各个元素 private: Node<T> *rear; //尾指针 }; /** 尾插法 用数组元素初始化循环单链表 思路: 1.新建一头结点,尾指针指向此头结点 2.将头结点地址赋值给头结点指针域 即构成了一个空的单循环链表 3.for循环 开始插入节点。 3.1新建一个结点,将数组元素赋值给结点的数据域 3.2使新建结点的指针域指向头结点的指针域 形成循环 3.3将当前结点指向新建结点 3.4尾指针向后移一位 */ template <class T> CLinkList<T>::CLinkList(T a[],int n) { rear = new Node<T>; rear->next = rear; //采用尾插法 for(int i=0;i<n;i++) { Node<T> *s= new Node<T>; s->data = a[i]; s->next = rear->next ; rear->next = s; rear = rear->next; //尾指针向后移 } } template <class T> int CLinkList<T>::GetLength() { int count = 0; //计数器 Node<T> *p = rear->next; while(p!=rear) { count++; p = p->next; } return count; } /** 析构函数 用来释放结点 */ template <class T> CLinkList<T>::~CLinkList() { Node<T> *p = rear->next; //初始化工作指针 Node<T> *q; //临时结点 while(p!=rear) { q = p; p = p->next; delete q; } } template <class T> T CLinkList<T>::Get(int i) { if(i>GetLength()||i<1) return -1; //判断查找的位置是否是合理的 Node<T> *p = rear->next; for(int j=0;j<i;j++) { p = p->next; //得到位置i的节点 } return p->data; } template <class T> int CLinkList<T>::Locate(T x) { Node<T> *p = rear->next; int j=0; while(p!=rear) { if(p->data==x) return j; j++; p = p->next; } return -1; } template<class T> void CLinkList<T>::Insert(int i,T x) { Node<T> *p = rear->next; //获取前一个结点 for(int j=0;j<i-1;j++) { p = p->next; } Node<T> *s = new Node<T>; s->data = x; s->next = p->next; p->next = s; } template <class T> void CLinkList<T>::PrintLinkList() { Node<T> *p = rear->next; //这里是头结点 for(int i=0;i<GetLength();i++) { cout<<p->next->data<<" "; //下一个节点的数据域 p = p->next; } cout<<endl; } template<class T> T CLinkList<T>::Delete(int i) { Node<T> *p = rear->next; for(int j=0;j<i-1;j++) { p = p->next; } Node<T> *q = p->next; //要删除的结点 p->next = q->next; T x = q->data; delete q; return x; } int main() { int a[6] = {2,4,6,1,7,9}; CLinkList<int> list(a,6); cout<<"遍历单链表的元素"<<endl; list.PrintLinkList(); cout<<"循环单链表的长度:"<<endl; cout<<list.GetLength()<<endl; cout<<"获取位置2的元素:"<<endl; cout<<list.Get(2)<<endl; cout<<"获取元素6所在的位置"<<endl; cout<<list.Locate(2)<<endl; cout<<"插入元素8到位置3"<<endl; list.Insert(3,8); list.PrintLinkList(); cout<<"栓出位置4上的元素"<<endl; list.Delete(4); list.PrintLinkList(); return 0; } </span>
结果:
时间: 2024-09-30 11:49:20