线性表
具有相同数据类型的n个数据元素的有限序列
数据元素可以仅仅是数组,也可以是自定义数据类型
线性表可以分两类:
顺序表
地址连续,类似数组,拥有下标,插入和删除元素时需要移动数据元素。
前驱,后继:当前元素的前一个和后一个元素,有且仅有一个
class List
{
public:
List(int size); //创建线性表
~List(); //析构清除指针
void ClearList(); //清空线性表
bool ListEmpty(); //判空
int ListLength(); //表长度
bool GetElem(int i, int *e); //获取特定值元素
int LocateElem(int *e); //定位元素
bool PriorElem(int *currentElem, int *preElem); //前驱元素
bool NextElem(int *currentElem, int *nextElem); //后继元素
void ListTraverse(); //遍历
bool ListInsert(int i, int *e); //插入
bool ListDelete(int i, int *e); //删除
private:
int *m_pList;//更改类型来存储不同数据类型,也可使用模板类
int m_iSize;
int m_iLength;
};
List::List(int size){
m_iSize = size;
m_pList = new int[m_iSize];
m_iLength = 0;
}
List::~List(){
delete[]m_pList;
m_pList = NULL;
}
void List::ClearList(){
m_iLength = 0;
}
bool List::ListEmpty(){ //C语言没有bool类型,大写的BOOL是人为的宏定义
if (m_iLength == 0)
return true;
else
return false;
//return m_iLength==0? true:false
}
int List::ListLength(){
return m_iLength;
}
bool List::GetElem(int i, int *e){
if (i < 0 || i >= m_iLength)
{
return false;
}
*e = m_pList[i];
return true;
}
int List::LocateElem(int *e){
for (int i = 0; i < m_iLength; i++){
if (m_pList[i] == *e)
return i;
}
return -1; //不存在
}
bool List::PriorElem(int *currentElem, int *preElem){
int temp = LocateElem(currentElem);
if (temp == -1)
return false;
else if(temp==0)//当前为第一个元素,无前驱
return false;
else{
*preElem=m_pList[temp - 1];
return true;
}
}
bool List::NextElem(int *currentElem, int *nextElem){
int temp = LocateElem(currentElem);
if (temp == -1)
return false;
else if (temp == m_iLength-1)//当前为最后一个元素,无后继
return false;
else{
*nextElem = m_pList[temp + 1];
return true;
}
}
void List::ListTraverse(){
for (int i = 0; i < m_iLength; i++){
cout<<m_pList[i]<<" ";
//m_pList[i].printCoordinate();
}
}
bool List::ListInsert(int i, int *e)
{
if (i < 0 || i >m_iLength) //=的情况允许,视为插入最后一个元素
return false;
for (int k=m_iLength-1; k>=i; k--){ //依次向后赋值,从最后开始,避免覆盖
m_pList[k + 1] = m_pList[k];
}
m_pList[i] = *e;
m_iLength++;
return true;
}
bool List::ListDelete(int i, int *e){
if (i<0 || i>=m_iLength){ //无=情况,没有下一个元素
return false;
}
*e = m_pList[i];
for (int k = i + 1; k < m_iLength; k++){ //依次向前赋值,从最前开始
m_pList[k - 1] = m_pList[k];
}
m_iLength--;
return true;
}
链表
对每个数据元素,除存放自身的信息,还要存放直接后继所在存储单元的地址(指针域和数据域),两部分信息组成一个节点,
不需要地址连续的存储单元,通过链建立元素之间的逻辑关系,插入删除操作不需要移动数据元素。
单链表:第一个元素为头节点,当结点指针指向NULL,单链表结束
循环链表:尾节点指向头节点,成一个环
双向链表:每个节点有两个指针域,方向相反
节点实现
class Node
{
public:
int data; //更改数据域实现存储不同数据类型
Node *next; //指针域
void printNode(){
cout << data << endl;
}
};
链表实现
class List
{
public:
List(); //链表长度为动态的
~List();
void ClearList();
bool ListEmpty();
int ListLength();
bool GetElem(int i, Node *pNode);
int LocateElem(Node *pNode);
bool PriorElem(Node *pCurrentNode, Node *pPreNode);
bool NextElem(Node *pCurrentNode, Node *pNextNode);
void ListTraverse();
bool ListInsert(int i, Node *pNode);
bool ListDelete(int i, Node *pNode);
bool ListInsertHead(Node *pNode); //头节点后插入节点
bool ListInsertTail(Node *pNode); //插入尾节点
private:
Node *m_pList;
int m_iLength;
};
List::List(){
m_pList = new Node; //创建头结点
m_pList->data = 0; //头结点数据域无意义,赋值0
m_pList->next = NULL; //头结点指针域无意义,赋初值为NULL
m_iLength = 0; //头结点不算在链表长度中
}
List::~List(){ //删除所有结点
ClearList(); //清楚除头节点
delete m_pList; //再清楚头节点
m_pList = NULL;
}
void List::ClearList(){ //保留头结点
Node *currentNode = m_pList->next; //Node的指针指向Node类中的Node指针类型next,此处为节点指针
while (currentNode != NULL){ //当前节点是否有后继
Node *temp = currentNode->next; //指向后继
delete currentNode; //删除当前
currentNode = temp; //之前的后继变成当前
}
m_pList->next = NULL;
}
bool List::ListEmpty(){
if (m_iLength == 0)
return true;
else
return false;
//return m_iLength==0? true:false
}
int List::ListLength(){
return m_iLength;
}
bool List::ListInsertHead(Node *pNode){
Node *temp = m_pList->next; //堆中申请内存,如果在栈中申请内存,函数运行完之后,内存将会被回收
Node *newNode = new Node;
if (newNode == NULL)
return false;
newNode->data = pNode->data; //传入数据赋值
m_pList->next = newNode; //当前链表指针指向插入元素
newNode->next = temp; //插入元素的下一节点指向原来的下一元素的下一节点
m_iLength++;
return true;
}
bool List::ListInsertTail(Node *pNode){
Node *currentNode = m_pList;
while (currentNode->next != NULL){ //获取最后节点指针
currentNode = currentNode->next;
}
Node *newNode = new Node; //传递数据
if (newNode == NULL)
return false;
newNode->data = pNode->data; //传入数据赋值
newNode->next = NULL; //使插入节点下一节点变成尾节点
currentNode->next = newNode; //当前节点的下一节点指向插入节点
m_iLength++;
return true;
}
bool List::ListInsert(int i, Node *pNode){
if (i<0 || i>m_iLength){ //=为尾节点
return false;
}
Node*currentNode = m_pList;
for (int k = 0; k < i; k++){
currentNode = currentNode->next; //遍历得到第i个节点(下一个节点赋给当前
}
Node *newNode = new Node;
if (newNode == NULL)
return false;
newNode->data = pNode->data; //插入节点赋值参数
newNode->next = currentNode->next; //插入节点下一节点指向当前节点下一节点
currentNode->next = newNode; //当前节点的下一节点指向插入节点
m_iLength++;
return true;
}
bool List::ListDelete(int i, Node *pNode){
if (i < 0 || i >= m_iLength){ //=不可取,是尾结点的下一个结点
return false;
}
Node *currentNode = m_pList;
Node *currentNodeBefore = NULL; //当前节点的上一节点
for (int k = 0; k <= i; k++){
currentNodeBefore = currentNode;
currentNode = currentNode->next;
}
currentNodeBefore->next = currentNode->next;//当前节点指向当前节点的下一节点
pNode->data = currentNode->data; //值传出
delete currentNode; //删除当前节点
currentNode = NULL;
m_iLength--;
return true;
}
bool List::GetElem(int i, Node *pNode){
if (i < 0 || i >= m_iLength){
return false;
}
Node *currentNode = m_pList;
for (int k = 0; k <= i; k++){
currentNode = currentNode->next;
}
pNode->data = currentNode->data;
return true;
}
int List::LocateElem(Node *pNode){
int count=0;
Node *currentNode = m_pList;
while (currentNode->next!=NULL){
currentNode = currentNode->next;
if (currentNode->data == pNode->data){
return count;
}
count++;
}
return -1;
}
bool List::PriorElem(Node *pCurrentNode, Node *pPreNode){
Node *currentNode = m_pList;
Node *tempNode = NULL;
while (currentNode->next != NULL){
tempNode = currentNode; //指向当前节点上一节点
currentNode = currentNode->next; //当前节点指向下一个节点
if (currentNode->data == pCurrentNode->data){
if (tempNode == m_pList){ //当前节点的上一节点是头节点,则无前驱
return false;
}
pPreNode->data = tempNode->data;
return true;
}
}
return false;
}
bool List::NextElem(Node *pCurrentNode, Node *pNextNode){
Node *currentNode = m_pList;
while (currentNode->next != NULL){
currentNode = currentNode->next;
if (currentNode->data == pCurrentNode->data){
if (currentNode->next==NULL){ //当前结点是最后节点,无后继
return false;
}
pNextNode->data = currentNode->next->data;//当前节点下一节的数据为后继
return true;
}
}
return false;
}
void List::ListTraverse(){
Node *currentNode = m_pList;
while (currentNode->next != NULL){
currentNode = currentNode->next;
currentNode->printNode();
}
}