有书共读《算法与数据结构题目最优解》(在线编程题总结2)

Posted 软件开发者社区

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了有书共读《算法与数据结构题目最优解》(在线编程题总结2)相关的知识,希望对你有一定的参考价值。

书籍:《算法与数据结构题目最优解》


该书第二章——《链表问题》,总结我已放在CSDN中,详见:


1、线性表的简介  

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

2、数组  

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

3、链表的分类(有篇博客总结得很全面

)  

(1)单向链表

(2)单向循环链表

(3)双向链表

(4)双向循环链表

4、单向链表  

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

5、单向循环链表  

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

6、双向链表  

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

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

7、双向循环链表  

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

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;
}

(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;
    }
};


以上是关于有书共读《算法与数据结构题目最优解》(在线编程题总结2)的主要内容,如果未能解决你的问题,请参考以下文章

程序员代码面试指南 IT名企算法与数据结构题目最优解 ,左程云著pdf高清版免费下载

挑战程序设计竞赛(算法和数据结构)——5.6搜索的应用——计算最优解java实现

我的2017OKR - 年中回顾

贪心算法和动态规划的区别与联系

数据结构与算法简记--动态规划理论

leetcode刷题-贪心算法(持续更新)