C++数据结构——链表

C++数据结构——链表

参考博客:

(1)实践:https://www.cnblogs.com/renyuan/archive/2013/05/21/3091524.html

(2)实践:https://blog.csdn.net/lg1259156776/article/details/47021505

(3)理论:数据结构(二)链表、链队列https://blog.csdn.net/lg1259156776/article/details/47018813

(4)理论:https://blog.csdn.net/lg1259156776/article/details/46993591

(5)官网教程:http://www.cplusplus.com/reference/list/list/

1、线性表的简介

       线性表是一种线性结构,它是由零个或多个数据元素构成的有限序列。线性表的特征是在一个序列中,除了头尾元素,每个元素都有且只有一个直接前驱,有且只有一个直接后继,而序列头元素没有直接前驱,序列尾元素没有直接后继。数据结构中常见的线性结构有数组、单链表、双链表、循环链表等。线性表中的元素为某种相同的抽象数据类型。可以是C语言的内置类型或结构体,也可以是C++自定义类型。

2、数组

       数组在实际的物理内存上也是连续存储的,数组有上界和下界。C语言中定义一个数组:数组下标是从0开始的,a[0]对应第一个元素。其中,a[0]称为数组a的下界,a[n]称为数组a的上界。超过这个范围的下标使用数组,将造成数组越界错误数组的特点是:数据连续,支持快速随机访问数组分为固定数组与动态数组。其中固定数组的大小必须在编译时就能够确认,动态数组允许在运行时申请数组内存。复杂点的数组是多维数组,多维数组实际上也是通过一维数组来实现的。在C语言中,可以通过malloc来分配动态数组,C++使用new。另外,C++的标准模板库提供了动态数组类型vector以及内置有固定数组类型array。

扫描二维码关注公众号,回复: 1812809 查看本文章

3、链表的分类(有篇博客总结得很全面:https://blog.csdn.net/baweiyaoji/article/details/76071053

(1)单向链表

(2)单向循环链表

(3)双向链表

(4)双向循环链表

4、单向链表

       单向链表是链表的一种。链表由节点所构成,节点内含一个指向下一个节点的指针,节点依次链接成为链表。因此,链表这种数据结构通常在物理内存上是不连续的。链表的通常含有一个头节点,头节点不存放实际的值,它含有一个指针,指向存放元素的第一个节点。

5、单向循环链表

       单向循环链表是另一种形式的链式存储结构,其特点是表中最后一个结点的指针域指向头结点,整个链表形成一个环。由此,从表中的任一结点出发均可找到表中的其他结点。

6、双向链表

       以上讨论的链式存储结构的特点只有一个指示直接后继的指针域,由此,从某个结点出发只能顺着指针往后寻找其他结点。若要寻找结点的直接的前驱,则需从表头指针出发。换句话说,在单链表中,NextElem的执行时间为O(1),而PriorElem的执行时间为O(n)。为克服单链表这种单向性的缺点,可利用双向链表。

       双向链表的每个结点除含有数据域外,还有两个指针域,分别指向直接前驱结点和直接后继结点。因此,从双向链表中的任一结点开始,均可方便地访问其前驱结点和后继结点。具体见博客:

https://blog.csdn.net/mianhuantang848989/article/details/72393561

7、双向循环链表

       和单向链表相比,多了一个前驱结点。如果他为空,那么next和prior都指向自己。而对于双循环链表,只需要最后一个元素的next指向head->next,head->next的prior指向最后一个节点即可。具体见博客:

https://blog.csdn.net/mianhuantang848989/article/details/72393561

8、实例分析

    若使用标准库,需添加#include <list>,下面是常见一些操作:

assign() 给list赋值 
back() 返回最后一个元素 
begin() 返回指向第一个元素的迭代器 
clear() 删除所有元素 
empty() 如果list是空的则返回true 
end() 返回末尾的迭代器 
erase() 删除一个元素 
front() 返回第一个元素 
get_allocator() 返回list的配置器 
insert() 插入一个元素到list中 
max_size() 返回list能容纳的最大元素数量 
merge() 合并两个list 
pop_back() 删除最后一个元素 
pop_front() 删除第一个元素 
push_back() 在list的末尾添加一个元素 
push_front() 在list的头部添加一个元素 
rbegin() 返回指向第一个元素的逆向迭代器 
remove() 从list删除元素 
remove_if() 按指定条件删除元素 
rend() 指向list末尾的逆向迭代器 
resize() 改变list的大小 
reverse() 把list的元素倒转 
size() 返回list中的元素个数 
sort() 给list排序 
splice() 合并两个list 
swap() 交换两个list 
unique() 删除list中重复的元素

(1)表的基本操作

#include <list>
#include <iostream>
using namespace std;

int main(){
	//list<int> L1{4,2,6,5};
	list<int> L1;
	list <int>::iterator L1_iter;
	L1.push_back(4);
	L1.push_back(2);
	L1.push_back(6);
	L1.push_back(5);
	
	L1.reverse();//反转
	for (L1_iter = L1.begin(); L1_iter != L1.end();L1_iter++){
		cout << " " << *L1_iter;
	}
	cout << endl;
	system("pause");
	return 0;
}

运行结果:

 5 6 2 4

(2)剑指offer面试题24——反转链表

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
        ListNode* pReverseHead = nullptr;
        ListNode* pNode = pHead;
        ListNode* pPrev = nullptr;
        
        while(pNode!=nullptr){//输入的链表不为空
            ListNode* pNext = pNode->next;
            if(pNext == nullptr)//只有一个节点
                pReverseHead = pNode;
            //存在多个节点时,交换
            pNode->next = pPrev;
            pPrev = pNode;
            pNode = pNext;
        }
        return pReverseHead;
    }
};

运行结果:

通过
您的代码已保存
答案正确:恭喜!您提交的程序通过了所有的测试用例

猜你喜欢

转载自blog.csdn.net/zichen_ziqi/article/details/80834814