慕课网学习笔记之数据结构一单链表(C++)

单链表示意图:
这里写图片描述
单链表的每个结点分别由数据域data和指针域next组成,data里面装的是数据,next里面装的是下一个数据所在的地址,由next我们就可以找到下一个数据,这里next作用相当于“链条”,把一个个数据连接起来,这样在存储中,我们可以不必像顺序那样连续的存储,而是分开来存储,这也能体现出单链表的***优点***,即更充分的使用内存;相对比一下,使用顺序表时,为了不使得溢出,就必须认为估测一个合适的大小,往往都偏大,甚至为了安全而申请的很大(数组),但是如果使用单链表就不会有这样的问题。
这是定义链表的结点:

#ifndef NODE_H
#define NODE_H

class Node
{
public:
	int data;	
	Node *next;
	void printNode();
} ;
#endif 

这是实现打印结点数据:

#include"Node.h"
#include<iostream>
using namespace std;

void Node::printNode()
{
	cout<<data<<endl;
}

这是List.h文件的代码:

/*		
	单链表 
*/
#ifndef LIST_H
#define LIST_H

#include"Node.h"
class List
{
public:
	List();								//创建线性表 
	~List();									//销毁线性表 
	void ClearList();							//清空 
	bool ListEmpty();							//判空 
	int  ListLength();							//获取线性表长度 
	bool GetElem(int i,Node *pNode);  				//获取指定元素 
	int LocateElem(Node *pNode);	  					 //定位元素 寻找第一个满足e的元素的位序 
	bool PriorElem(Node *currentElem,Node *pPreNode);//获取指定元素的前驱 
	bool NextElem(Node *currentElem,Node *pNextNode);//获取指定元素的后继 
	void ListTraverse();					//遍历线性表 
	bool ListInsert(int i,Node *pNode);			//在第i个位置插入元素 
	bool ListDelete(int i,Node *pNode);			//删除第i个位置的元素 
	bool ListInsertHead(Node *pNode);
	bool ListInsertTail(Node *pNode);
private:
	Node *m_pList;		
	int  m_iLength;//当前长度 
};
#endif

这是List.cpp文件的代码:

// List.cpp : 定义控制台应用程序的入口点。
//
#include<iostream>
#include"List.h"
using namespace std;

List::List()
{
	
	m_pList = new Node;
	m_pList->data = 0;
	m_pList->next = NULL;
	m_iLength = 0;
}
List::~List()
{
	ClearList();
	delete m_pList;
	m_pList = NULL;
}
void List::ClearList()
{
	Node *currentNode = m_pList->next;
	while(currentNode!=NULL)
	{
		Node *temp = currentNode->next;
		delete currentNode;
		currentNode = temp;
	}
	m_pList->next =NULL;
	m_iLength = 0;
}
bool List::ListEmpty()
{
	if (0 == m_iLength)
		return true;
	else
		return false;

}
int List::ListLength()
{
	return m_iLength;
}
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)
{
	
	Node *currentNode = m_pList;
	int count=0;
	while(currentNode->next!=NULL)		
	{
		currentNode = currentNode->next;
		if(currentNode->data == pNode->data)
		{
			return count;			//小细节:当有重复时,只会返回第一次出现的 
		}
		count++;//为什么放后面?小细节:头节点数据域无意义,0是我们找到的头节点后的第一个节点 
	}
	return -1;
}

bool List::PriorElem(Node *pCurrentNode, Node *pPreNode)
{

	Node *currentNode = m_pList;
	Node *currentNodeBefore =NULL;
	while(currentNode->next!=NULL)		
	{
			currentNodeBefore=currentNode;
			currentNode = currentNode->next;
		if(currentNode->data == pCurrentNode->data)
		{
			if(currentNodeBefore == m_pList)
				return false;
			pPreNode->data=currentNodeBefore->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();
	}
	cout<<"m_iLength = "<<m_iLength<<endl;
}



bool List::ListInsertHead(Node *pNode)
{
	Node *temp = m_pList->next;  //头节点指向下一个结点的地址赋给temp保存起来
	Node *newNode = new Node;
	if(newNode == NULL)        //如果申请内存失败
		return false;
	newNode ->data = pNode->data;//数据域先赋给新结点
	m_pList->next = newNode;     //头结点与新结点连接
	newNode->next = temp;	    //新结点与后面结点连接的
	m_iLength++;                //插入成功长度加1
	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++;           //插入成功长度加1
	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;		
	}	
	Node *newNode = new Node;      //申请新结点
	if(newNode == NULL)          //申请是否成功
		return  false;
	newNode->data = pNode->data;  //数据域传入
	newNode->next=currentNode->next;//当前结点所指向的下一结点的地址传给新结点
	currentNode->next=newNode;//当前结点与新结点连接
	m_iLength ++;              //插入成功长度加1
	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;       //为了安全指为NULL
	m_iLength--;            //删除成功长度-1
	return true; 
}

上面代码中插入与删除配合结构图更便于理解,结构图示意图如下:
这里写图片描述
这里写图片描述

这是验证代码domo.cpp文件:

#include<iostream>
#include"List.h" 
using namespace std;

int main(void)
{
	Node node1;
	node1.data=3;
	Node node2;
	node2.data=4;
	Node node3;
	node3.data=5;
	Node node4;
	node4.data=6;
	Node node5;
	node5.data=77;
	List *pList = new List();
	cout<<"从头部插入:"<<endl; 
	pList->ListInsertHead(&node1);
	pList->ListInsertHead(&node2);
	pList->ListInsertHead(&node3);
	pList->ListInsertHead(&node4);
	
	pList->ListTraverse();
	cout<<"清除~~~";
	pList->ClearList();
	cout<<"清除~~~DONE"<<endl;

	cout<<"从尾部插入:"<<endl; 
	pList->ListInsertTail(&node1);
	pList->ListInsertTail(&node2);
	pList->ListInsertTail(&node3);
	pList->ListInsertTail(&node4);
	pList->ListTraverse();
	cout<<"从位置2插入 :"<<endl; 
 	pList->ListInsert(2,&node5);
	pList->ListTraverse();
	
	cout<<"从位置3删除 :"<<endl;
	Node temp;
	pList->ListDelete(3,&temp); 
	pList->ListTraverse();
	
	cout<<"从位置1取出放入temp"<<endl ;
	pList->GetElem(1,&temp);
	cout<<"temp = "<<temp.data<<endl; 
	
	pList->PriorElem(&node2,&temp);
	cout<<"从位置1取前驱temp"<<endl ;
	cout<<"temp = "<<temp.data<<endl; 
	pList->NextElem(&node2,&temp);
	cout<<"从位置1取后继temp"<<endl ;
	cout<<"temp = "<<temp.data<<endl; 

	cout << "isEmpte:"<<boolalpha<<pList->ListEmpty()<<endl;
		
	delete pList;
	pList = NULL;
	
	return 0;
}

运行如图:
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值