算法与数据结构基础-线性表

线性表

具有相同数据类型的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();
	}
}
  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jason 20

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值