数据结构一:线性表
Posted Hot_Destiny
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构一:线性表相关的知识,希望对你有一定的参考价值。
线性表是最常用也是最简单的数据结构,几种常用的线性表的类模板C++描述描述如下:
1.顺序表
顺序表是将所有元素按逻辑顺序存储在一组地址连续的存储空间中的简单数据结构:
1 const int MAXSIZE = 1000; 2 template<class T> 3 class SeqList 4 { 5 public: 6 SeqList(){ lenght = 0; } // 无参构造函数 7 SeqList(const T a[], int n); // 带参构造函数,并用数组初始化 8 9 int GetLenght() const{ return lenght; }// 返回顺序表长度 10 void PrintList()const; // 依次遍历顺序表各个数据元素 11 void Insert(int i, T x); // 指定位置插入数据元素 12 T Delete(int i); // 删除指定位置的数据元素,并返回这个元素 13 T Get(int i) const; // 获取指定位置的数据元素 14 int Locate(T x) const; // 查找指定元素并返回其位置 15 private: 16 T data[MAXSIZE]; // 存储顺序表中各个数据元素 17 int lenght; // 顺序表长度 18 }; 19 20 21 // 构造函数 22 template<class T> 23 SeqList<T>::SeqList(const T a[], int n) 24 { 25 if (n > MAXSIZE) 26 throw"数组长度超出顺序表最大长度"; 27 for (int i = 0; i < n; i++) 28 data[i] = a[i]; 29 lenght = n; 30 } 31 32 // 遍历顺序表 33 template<class T> 34 void SeqList<T>::PrintList()const 35 { 36 std::cout << "顺序表中元素依次如下所示:" << endl; 37 for (int i = 0; i < lenght; i++) 38 std::cout << data[i] << " "; 39 std::cout << std::endl; 40 } 41 42 // 插入元素 43 template<class T> 44 void SeqList<T>::Insert(int i, T x) 45 { 46 if (lenght >= MAXSIZE) 47 throw"上溢异常"; 48 if (i<1 || i>lenght) 49 throw"插入位置不合法"; 50 for (int j = lenght; j >= i; j--) 51 data[j] = data[j - 1]; 52 data[i - 1] = x; 53 lenght++; 54 } 55 56 // 删除元素 57 template<class T> 58 T SeqList<T>::Delete(int i) 59 { 60 if (0 == lenght) 61 throw"下溢异常"; 62 if (i<1 || i>lenght) 63 throw"删除位置不合法"; 64 T X = data[i - 1]; 65 for (int j = i; j < lenght; j++) 66 data[j - 1] = data[j]; 67 lenght--; 68 return X; 69 } 70 71 // 查找元素 72 template<class T> 73 T SeqList<T>::Get(int i)const 74 { 75 if (i<1 || i>lenght) 76 throw"查找位置不合法"; 77 78 return data[i - 1]; 79 } 80 81 // 定位元素 82 template<class T> 83 int SeqList<T>::Locate(T x)const 84 { 85 for (int i = 0; i < lenght; i++) 86 { 87 if (x == data[i]) 88 return i + 1; 89 } 90 91 throw"查找的元素不存在顺序表中"; 92 return 0; 93 }
2.单链表
单链表与顺序表不同的地方是存放的元素地址是零散的,可能连续也可能不连续,保证彼此之间的联系,因此,在存储元素的时候需要存储下一个元素的地址:
1 template<class T> 2 struct Node 3 { 4 T data; 5 Node*next; 6 }; 7 8 9 template<class T> 10 class LinkList 11 { 12 public: 13 LinkList(){ front = new Node<T>; front->next = NULL; }// 无参构造函数 14 LinkList(T a[], int n); // 带参构造函数,用数组初始化链表 15 ~LinkList(); // 析构函数 16 void PrintList()const; // 依次遍历链表元素 17 int GetLenght()const; // 返回链表长度 18 Node<T>*Get(int i)const; // 返回指定位置的数据元素 19 int Locate(T x)const; // 查找指定元素,并返回其位置 20 void Insert(int i, T x); // 指定位置插入指定元素 21 T Delete(int i); // 删除指定位置的元素 22 private: 23 Node<T>*front; // 头指针 24 }; 25 26 27 // 头插法 28 template<class T> 29 LinkList<T>::LinkList(T a[], int n) 30 { 31 front = new Node<T>; 32 front->next = NULL; // 构造空链表 33 for (int i = n - 1; i => 0;i--) 34 { 35 Node<T>*s = new Node<T>; // 建立新结点 36 s->data = a[i]; // 将值写入结点数据域 37 s->next = front->next; // 修改新节点指针域 38 front->next = s; // 修改头结点指针域 39 } 40 } 41 42 // 尾插法 43 template<class T> 44 LinkList<T>::LinkList(T a[], int n) 45 { 46 front = new Node<T>; 47 Node<T>*r = front; 48 for (int i = 0; i < n;i++) 49 { 50 Node<T>*s = new Node<T>; // 建立新结点 51 s->data = a[i]; // 将值写入新结点数据域 52 r->next = s; // 将新结点加入链表 53 r = s; // 修改尾指针 54 } 55 r->next = NULL; 56 } 57 58 template<class T> 59 LinkList<T>::~LinkList() 60 { 61 Node<T>*p = front; // 初始化工作指针 62 while (p) 63 { 64 front = p; // 暂存工作指针 65 p = p->next; // 移动工作指针到下一个结点 66 delete front; // 释放结点 67 } 68 } 69 70 template<class T> 71 Node<T>*LinkList<T>::Get(int i)const 72 { 73 Node<T>*p = front->next; // 初始化工作指针 74 int j = 1; // 初始化计数器 75 while (p&&j!=i) 76 { 77 p = p->next; // 移动工作指针 78 j++; // 计数器递增 79 } 80 return p; // 返回查找结果 81 } 82 83 template<class T> 84 int LinkList<T>::Locate(T x)const 85 { 86 Node<T>*p = front->next; // 初始化工作指针 87 int j = 1; // 初始化计数器 88 while (p) 89 { 90 if (x == p->data) // 找到指定元素就返回位置 91 return j; 92 p = p->next; // 移动工作指针 93 j++; // 递增计时器 94 } 95 return -1; // 若找不到,返回-1 96 } 97 98 template<class T> 99 void LinkList<T>::Insert(int i, T x) 100 { 101 Node<T>*p = front; // 初始化工作指针 102 103 if (i != 1) 104 p = Get(i - 1); // 返回插入位置前一个元素的位置 105 if (p) 106 { 107 Node<T>*s = new Node<T>; 108 s->data = x; // 插入元素数据区域赋值 109 s->next = p->next; // 插入元素指针区域赋值 110 p->next = s; // 插入元素接入链表 111 } 112 else 113 throw"插入位置错误!"; 114 } 115 116 template<class T> 117 T LinkList<T>::Delete(int i) 118 { 119 Node<T>*p = front; // 初始化工作指针 120 if (i != 1) 121 p = Get(i - 1); // 获取第i-1个元素的地址 122 Node<T>*q = p->next; // 获取第i个元素的地址 123 p->next = q->next; // 将第i+1个元素与第i个元素链接 124 T x = q->data; // 保存被删除元素 125 delete q; // 删除指定位置元素 126 return x; // 返回被删除的元素 127 } 128 129 template<class T> 130 void LinkList<T>::PrintList()const 131 { 132 Node<T>*p = front->next; 133 std::cout << "链表元素依次为:"; 134 while (p) 135 { 136 std::cout << (p->data) << " "; 137 p = p->next; 138 } 139 std::cout << std::endl; 140 } 141 142 template<class T> 143 int LinkList<T>::GetLenght()const 144 { 145 Node<T>*p = front->next; 146 int j = 1; 147 while (p) 148 { 149 p = p->next; 150 j++; 151 } 152 153 return j; 154 }
3.单循环链表
单循环链表与单链表没有太大区别,为了访问链表的首尾段,将之前的头指针换成了尾指针,尾指针指向链表尾部,尾指针指针域指向链表第一个元素:
1 template<class T> 2 struct Node 3 { 4 T data; // 数据域 5 Node*next; // 指针域 6 } 7 8 template<class T> 9 class CLinkList 10 { 11 public: 12 CLinkList(){ rear = new Node<T>; rear->next = rear; } // 无参构造函数 13 CLinkList(T a[], int n); // 用数组初始化单循环链表 14 15 ~CLinkList(); // 析构函数 16 int GetLenght()const; // 返回链表长度 17 Node<T>*Get(int i)const; // 返回指定位置元素数据 18 int Locate(T x)const; // 查找指定元素,并返回其位置 19 void Insert(int i, T x); // 指定位置插入元素 20 T Delete(int i); // 删除指定位置的元素,并返回其值 21 void PrintList()const; // 依次遍历链表元素 22 void Connect(CLinkList<T>&B); // 将链表B链接到表尾 23 24 private: 25 Node<T>*rear; // 尾指针(指向最后一个元素) 26 }; 27 28 29 template<class T> 30 CLinkList<T>::CLinkList(T a[], int n) // 尾插法 31 { 32 rear = new Node<T>; 33 rear->next = rear; // 初始化尾指针 34 for (int i = 0; i < n; i++) 35 { 36 Node <T>*s = new Node <T>; 37 s->data = a[i]; // 数据域赋值 38 s->next = rear->next;// 新增结点指针指向头结点 39 rear->next = s; // 新增结点添加到链表中 40 rear = s; // 尾指针指向尾结点 41 } 42 } 43 44 45 template<class T> 46 void CLinkList<T>::PrintList()const 47 { 48 std::cout << "单循环链表各元素如下:"; 49 Node<T>*p = rear->next; // 初始化工作指针指向头结点 50 do 51 { 52 p = p->next; // 修改工作指针 53 std::cout << p->data << " "; // 打印 54 } while (p != rear); 55 56 std::cout << std::endl; 57 } 58 59 template<class T> 60 CLinkList<T>::~CLinkList() 61 { 62 Node<T>*p = rear->next; // 初始化工作指针 63 Node<T>*q = rear->next; // 初始化工作指针 64 while (p!=rear) 65 { 66 q = p; 67 p = p->next; 68 delete q; 69 } 70 delete p; // 释放尾结点 71 } 72 73 74 template<class T> 75 int CLinkList<T>::GetLenght()const 76 { 77 Node<T>*p = rear->next; // 初始化工作指针 78 int j = 0; // 元素计数器 79 while (p != rear) 80 { 81 p = p->next; // 移动工作指针 82 j++; 83 } 84 return j; 85 } 86 87 template<class T> 88 Node<T>*CLinkList<T>::Get(int i)const 89 { 90 Node<T>*p = rear->next; // 初始化工作指针 91 int j = 0; // 计数器 92 while ((p != rear) && (j != i)) 93 { 94 p = p->next; // 移动工作指针 95 j++; 96 } 97 return p; 98 } 99 100 template<class T> 101 int CLinkList<T>::Locate(T x)const 102 { 103 Node<T>*p = rear->next; // 初始化工作指针 104 int j = 0; // 计数器 105 while (p != rear) 106 { 107 if (p->data == x) 108 return j; 109 p = p->next; // 移动工作指针 110 j++; 111 } 112 return -1; 113 } 114 115 template<class T> 116 T CLinkList<T>::Delete(int i) 117 { 118 Node<T>*P = rear; // 初始化工作指针 119 if (i != 1) 120 P = Get(i - 1); // 获取第i-1个元素的地址 121 Node<T>*q = P->next; // 获取第i个元素的地址 122 P->next = q->next; // 将第i+1个元素与第i个元素链接 123 T x = q->data; // 保存被删除元素 124 delete q; // 删除指定位置元素 125 return x; // 返回被删除的元素 126 } 127 128 template<class T> 129 第02次作业-线性表