数据结构与算法之线性表

接上文:https://blog.csdn.net/weixin_43217963/article/details/88723766

3.链表

3.1单链表

链式存储:用一组任意的存储单元存储线性表中的数据元素(可以使连续的,也可以是不连续的),数据元素之间的逻辑关系借助指示元素存储位置的指针来表示。

链表的每个节点由两部分组成:数据域data和指针域*next。

  • 数据域用来存放该节点的数据元素本身的信息;指针域用来指向下一个结点的存储位置。

线性链表的特点

  • 结点在存储器的位置是任意的,节点之间的逻辑关系由结点中的指针来指示。
  • H是指针变量,该变量保存着指向单链表的第一个结点的指针,称为头指针。(头结点中数据域不存放信息,指针域即为头指针)对单链表中任一结点的访问必须从头指针开始。最后一个结点的指针指向NULL。

3.2其他链表
链表又分为单链表、循环链表、双向链表、双向循环链表。

循环链表:循环链表是一种首尾相接的链表。在单链表中,如果最后一个结点的指针域的值不是NULL而是指向头结点,则为循环链表。

  • 其特点是从表中任意结点出发均可找到表中其他的结点
  • 单循环链表与单链表操作基本一致,但需要将算法中的循环条件p->next是否为空改为是否等于头指针。

双向链表:在单链表的基础上,再加上一个指向前驱的指针域,这样,链表的每一个结点中有一个数据域data,两个指针域(一个指向直接前驱prior,一个指向直接后继next),则为双向链表。

  • 显然,双向链表中找每一个结点的前驱后继都很方便

双向循环链表:和单循环链表一样,将双向链表的头结点和尾结点链接起来,就形成了双向循环链表。

  • 双向循环链表是将头结点的前驱指针指向了尾结点,同时尾结点的后继指针指向了头结点。
  • 空的双向循环链表中,头结点的前驱和后继指针均指向了自己,这是其判空条件。

3.3单链表代码示例:
c语言的定义实现:

typedef int elemtype;
typedef struct node
{
	elemtype data;//数据域
	struct node *next;指针域
}Lnode;

c++实现单链表
node.h

#ifndef NODE_H
#define NODE_H

#include<iostream>
using namespace std;
class Node
{
public:
	int data;
	Node *next;
	void printInfo()
	{
		cout << data << endl;
	}
};

#endif

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);//获取第i个结点
	int LocateElem(Node *pNode);     //获取第一个满足e的结点的位序
	//bool PriorElem(Node *pCrrentNode, Node *pPreNode);//找出给定结点的前驱
	//bool NextElem(Node *pCrrentNode, Node *pNextNode);//找出给定结点的后继
	bool ListInsert(int i, Node *pNode);//第i个位序插入结点
	bool ListDelete(int i, Node *pNode);//删除第i个位序的结点
	void ListTraverse();//遍历
	bool ListInsertHead(Node *pNode);//在第一个结点之前插入元素
	bool ListInsertTail(Node *pNode);//在最后一个结点后插入元素
private:
	Node *m_pList;
	int m_iLen;
};

#endif

list.cpp

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

List::List()
{
	m_pList = new Node;      //创建头结点
	m_pList->data = 0;
	m_pList->next = NULL;
	m_iLen = 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;
}

bool List::ListEmpty()
{
	return m_iLen == 0 ? true : false;
}

int List::ListLength()
{
	return m_iLen;
}

bool List::ListInsert(int i, Node *pNode)
{
	if (i<0 || i>m_iLen)
		return false;
	Node *currentNode = m_pList;
	for (int j = 0; j < i; j++)//找到第i-1个位序结点
	{
		currentNode = currentNode->next;
	}
	Node *newNode = new Node;
	if (newNode == NULL)
		return false;
	newNode->data = pNode->data;
	newNode->next = currentNode->next;
	currentNode->next = newNode;
	return true;
}

bool List::ListDelete(int i, Node *pNode)
{
	if (i<0 || i>=m_iLen)
		return false;
	Node *currentNode = m_pList;
	for (int j = 0; j < i; j++)//找到第i-1个位序结点
	{
		currentNode = currentNode->next;
	}
	Node *temp = currentNode->next;
	pNode->data = temp->data;
	currentNode->next = temp->next;
	delete temp;
	m_iLen--;
	return true;
}

bool List::GetElem(int i, Node *pNode)
{
	if (i < 0 || i >= m_iLen)
		return false;
	Node *preNode = m_pList;
	for (int j = 0; j < i - 1; j++)//找到第i-1个结点
	{
		preNode = preNode->next;
	}
	pNode->data = preNode->next->data;
	return true;
}

int List::LocateElem(Node *pNode)
{
	Node *currentNode = m_pList;
	int count = 1;
	while (currentNode->next != NULL)
	{
		currentNode = currentNode->next;
		if (currentNode->data == pNode->data)
		{
			return count;
		}
		count++;
	}
	return -1;
}

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_iLen++;
	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;
	currentNode->next = newNode;
	newNode->next = NULL;
	m_iLen++;
	return true;
}

void List::ListTraverse()
{
	Node *currentNode = m_pList;
	while (currentNode->next != NULL)
	{
		currentNode = currentNode->next;
		currentNode->printInfo();
	}
}

main.cpp

#include<iostream>
#include"list.h"
#include"node.h"

int main(void)
{
    //测试
	/*Node node1;
	node1.data = 3;
	Node node2;
	node2.data = 4;
	Node node3;
	node3.data = 5;
	Node node4;
	node4.data = 10;
	Node node5;
	
	List *pList = new List;
	pList->ListInsertHead(&node1);
	pList->ListInsertHead(&node2);
	pList->ListInsertHead(&node3);
	pList->ListInsert(2, &node4);
	pList->ListDelete(2, &node5);
	pList->ListTraverse();*/


	system("pause");
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值