题目:建立一个循环单链表,其节点有 prior,data 和 next 三个域,其中 data 为数据域,存放元素的有效信息,next 域为指针域,指向后继节点,prior 为指针域,它的 值为 NULL。编写一个算法将此表改为循环双链表。
算法描述:首先你需要有一个循环单链表,但是他的节点有两个指针域一个数据域。在初始化的时候就让所有的prior指向nullptr,让这个指针失去作用,之后的操作和普通的循环单链表是一样的。在循环单链表建立之后,我们在对所有节点的prior指针进行指向就可以完成循环双链表的改造。
已建有一个单循环链表(带头结点),first 指向头结点。设 立两个工作指针 p 和 q,分别指向头结点和第 1 个结点;执行 q->prior=p;,建立第 1 个结点的前驱指针,如图 1-4 所示;同步移动工作指针 p 和 q 分别指向下一个结点, 如图 1-5 所示,建立 q 指向结点的前驱,直到 q==first 为止,再将头结点的前驱设为 最后一个结点。
LinkList.h
1 #ifndef LinkList_H //避免重复包含LinkList.h头文件 2 #define LinkList_H 3 4 // 定义链表结点 5 template <typename DataType> struct Node 6 { 7 DataType data; 8 struct Node<DataType> *prior, *next; 9 }; 10 11 //定义链表 12 template <typename DataType> class LinkList 13 { 14 public: 15 LinkList(); // 只有头结点的空链表 16 LinkList(DataType a[], int n); // 建立n个元素的单链表 17 ~LinkList(); // 析构函数 18 void printlist(); // 用尾指针遍历链表 19 void arithmetic(); // 法将此表改为循环双链表 20 private: 21 struct Node<DataType> *first; // 头指针 22 }; 23 #endif
LinkList.cpp
1 # include <iostream> 2 # include <cstdlib> 3 using namespace std; 4 # include "LinkList.h" 5 6 // 无参数构造函数 7 template <typename DataType> LinkList<DataType>::LinkList() 8 { 9 first = new Node<DataType>; 10 first->next = first; 11 first->prior = NULL; 12 } 13 14 // 有参数构造函数 15 template <typename DataType> LinkList <DataType>::LinkList(DataType a[], int n) 16 { 17 first = new Node<DataType>; 18 first->next = first; 19 first->prior = NULL; 20 for (int i = 0; i <n; i++) 21 { 22 Node<DataType> *s = NULL; 23 s = new Node<DataType>; 24 s->data = a[i]; 25 s->prior = NULL; 26 s->next = first->next; 27 first->next = s; 28 } 29 } 30 31 // 析构函数 32 template <typename DataType> LinkList<DataType>::~LinkList() 33 { 34 Node<DataType> *p = first; // 建立工作指针 35 while (first != NULL) 36 { 37 first = first->next; 38 delete p; 39 p = first; 40 } 41 } 42 43 // 用尾指针遍历链表 44 template <typename DataType> void LinkList<DataType>::printlist() 45 { 46 Node<DataType> *p = first->next; // 建立工作指针 47 cout<<"利用后继指针遍历链表:"<<endl<<'\t'; 48 while (p != first) // 当工作指针p指向头结点时遍历结束 49 { 50 cout<<p->data<<"\t"; 51 p = p->next; 52 } 53 cout<<endl; 54 } 55 56 // 法将此表改为循环双链表 57 template <typename DataType> void LinkList<DataType>::arithmetic() 58 { 59 if (first->next == first) throw "这个链表只有头结点"; 60 61 Node<DataType> *p = first, *q = p->next; // 建立工作指针,p指向头结点,q指向首节点 62 63 while (q != first) 64 { 65 q->prior = p; 66 p = p->next; 67 q = q->next; 68 } 69 70 71 72 q->prior = p; // 当q指向头结点,p指向尾结点,将头结点的前驱指向尾结点 73 cout<<"已经将链表改造成循环双链表!"<<endl; 74 cout<<"利用前驱指针遍历链表:"<<endl<<'\t'; 75 while (p != first) // 当工作指针p指向头结点时遍历结束 76 { 77 cout<<p->data<<"\t"; 78 p = p->prior; 79 } 80 cout<<"\n\n\n"; 81 82 }
LinkList_main.cpp
1 # include "LinkList.cpp" 2 3 int main(void) 4 { 5 int A[7] = {1, 2, 3, 4, 5, 6, 7}; 6 int B[10] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; 7 8 LinkList<int> L1(A, 7); // 使用有参构造函数创建链表 9 L1.printlist(); 10 L1.arithmetic(); 11 12 13 LinkList<int> L2(B,10); // 使用有参构造函数创建链表 14 L2.printlist(); 15 L2.arithmetic(); 16 17 system("pause"); 18 return 0; 19 }