大话数据结构之线性表--链式存储结构单链表的c++实现

目录

  • 数据结构之线性表
    • 基本概念
    • 线性表的存储结构
      • 顺序存储
      • 链式存储
    • 链式存储结构单链表的C++实现
      • 单链表的存储结构
      • 判断链表是否为空链表
      • 返回链表的长度
      • 寻找元素
      • 获取元素
      • 插入节点
      • 删除节点
      • 头插法创建单链表
      • 尾插法创建单链表
      • 单链表的整表删除
      • 打印单链表
      • 完整代码

本文简单介绍了线性表的基本概念以及具体的代码实现,并在文末提供了代码下载链接。如果有错误的地方还请不吝赐教!

数据结构之线性表

基本概念

线性表零个或多个数据元素的有限序列。
属性:第一个元素没有直接前驱元素和最后一个元素没有直接后继元素,其他每个元素有且仅有一个直接前驱和直接后继元素。
基本操作:创建、增删查改。

线性表的存储结构

分为顺序存储链式存储。下面分别介绍片两种存储结构的优缺点。

顺序存储

优点: 随机存取结构,查改操作的时间复杂度为O(1)。
缺点:增删操作的时间复杂度为O(n),空间分配过小容易溢出,空间分配过大容易浪费资源。
注意:数组存储线性表,线性表的长度小于等于数组的长度。

链式存储

优点:多次在同一个位置的插入或删除数据,时间复杂度为O(1)。
1、遍历查找第i个结点,时间复杂度为O(n);
2、插入或删除一个结点,时间复杂度为O(1)。

链式存储结构单链表的C++实现

下面讲解链式存储结构单链表的C++实现,完整代码请在这里下载。

单链表的存储结构

//链表存储结构
struct ListNode
{
	int val;
	struct ListNode *next;
	ListNode(int x) : val(x), next(NULL) {}
	ListNode() = default;
};//包含数据和指针

判断链表是否为空链表

bool ListTable::ListEmpty(ListNode* head)
{
	if (head == NULL)
		return true;
	else
		return false;
}

返回链表的长度

int ListTable::ListLength(ListNode* head)
{
	ListNode* h = head;
	int res = 0;
	while (h)
	{
		h = h->next;
		res++;
	}
	return res;
}

寻找元素

在链表中寻找与elem相等的元素,有的话返回元素序号,没有的话返回-1表示失败。

int ListTable::LocateElem(ListNode* head, int elem)
{
	ListNode* h = head;
	int i=0;
	while (h)
	{
		if (h->val == elem)
			return i;
		h = h->next;
		i++;
	}
	return -1;
}

获取元素

bool ListTable::GetElem(ListNode* head, int i, int& elem)
{
	int j;
	ListNode* p;
	p = head;
	j = 0;
	while (p && j < i)
	{
		p = p->next;
		++j;
	}
	if (!p || j > i)
		return false;
	elem = p->val;
	return true;
}

插入节点

bool ListTable::ListInsert(ListNode* &head, int i, int elem)
{
	int j;
	ListNode* p, *s;
	p = head;
	j = 0;
	if (i == 0)//如果插入第0个元素
	{
		s = new ListNode(elem);//将要插入的元素
		s->next = head;
		//std::cout << s->val << std::endl;
		head = s;
		return true;
	}
	while (p && j < i-1)//寻找第i-1个节点
	{
		p = p->next;
		++j;
	}
	if (!p || j > i)
		return false;
	s = new ListNode(elem);//将要插入的元素
	//下面两行代码一定不能反,标准的链表插入语句
	s->next = p->next;
	p->next = s;
	return true;
}

删除节点

//删除第i个节点,并将删除的元素保存在elem;
bool ListTable::ListDelete(ListNode* &head, int i, int& elem)
{
	int j;
	ListNode* p, *s;
	p = head;
	j = 0;
	if (i == 0)//如果删除第0个元素
	{
		elem = head->val;
		head = head->next;
		return true;
	}
	while (p && j < i - 1)//寻找第i-1个节点
	{
		p = p->next;
		++j;
	}
	if (!p->next || j > i)
		return false;
	s = p->next;
	elem = s->val;//保存删除的元素
	p->next = s->next;
	delete s;//释放内存
	return true;
}

头插法创建单链表

void ListTable::CreateListHead(ListNode* &head, int n)
{
	ListNode *p;
	int i;
	srand(time(NULL));
	head = new ListNode();
	std::cout <<"头插法原始生成的数据:"<< std::endl;
	for (i = 0; i < n; i++)
	{
		p = new ListNode();
		p->val = rand() % 100 + 1;
		std::cout << p->val <<" ";
		p->next = head->next;
		head->next = p;
	}
	std::cout << std::endl;
	head = head->next;
}

尾插法创建单链表

void ListTable::CreateListTail(ListNode* &head, int n)
{
	ListNode *p, *r;//r为尾部节点
	int i;
	srand(time(NULL));
	head = new ListNode();
	r = head;//不能改变原始的head数据
	std::cout << "尾插法原始生成的数据:" << std::endl;
	for (i = 0; i < n; i++)
	{
		p = new ListNode();
		p->val = rand() % 100 + 1;
		std::cout << p->val << " ";
		r->next = p;
		r = r->next;
	}
	std::cout << std::endl;
	head = head->next;
}

单链表的整表删除

bool ListTable::ClearList(ListNode* &head)
{
	ListNode *p, *q;
	p = head;
	q = head;
	while (p)
	{
		q = p->next;//保留下一个节点
		delete p;//释放空间
		p = q;
	}
	head = NULL;
	return true;

}

打印单链表

void ListTable::printList(ListNode* head)
{
	std::cout << "==========现在开始打印链表==========" << std::endl;
	ListNode* l = head;
	while (l)//l不为空则继续进行循环
	{
		std::cout << l->val << " ";
		l = l->next;//l指向下一个元素
	}
	if (l == NULL)
		std::cout << "这是一个空链表!" << std::endl;
	else 
		std::cout << std::endl;
	std::cout << "==========链表打印完毕==========" << std::endl;
}

完整代码

完整代码请在这里下载。

你可能感兴趣的:(数据结构,数据结构,链表)