数据结构笔记(一):数组、链表

   日期:2024-01-17     浏览:46    评论:0    

(一)数组

数组(Array)是一种线性表数据结构。它用一组连续的内存空间,来存储一组具有相同类型的数据。

1、数组支持随机访问,根据下标随机访问的时间复杂度为 O(1)

   通过 a[i]_address = a[0]_address + i*元素的大小(字节) ,得到a[i]所在的位置。

2、插入:

  数组长度为n,在索引k插入一个元素,k~n的元素都需要向后搬移。时间复杂度为O(n) 。(在末尾插入时间复杂度O(1),首位插入则为On,平均时间复杂度为On))

  如果数组是无序的,可以在末尾插入,再和第k个元素互换,实现O1)时间复杂度复杂度的插入。

3、删除

 和插入类似。数组长度为n,删除第k个元素,则k+1~n的元素都需要向前搬移一位,时间复杂度为o(n)

    如果数组是无序的,可以将末尾的元素和第k个元素互换位置,然后再删除,实现O(1)时间复杂度的删除。

 

(二)链表

1、数组与链表在底层存储结构上的区别

(1)数组需要一段连续的内存空间,链表则不需要

(2)链表通过“指针”,将一组零散的内存空间串联在一起。

2、常用的链表结构

(1)单链表

(2)双向链表

(3)循环链表

3、单链表

 

 

 

(1)把内存块(data)称为链表的“结点”,用于存储数据。next记录下一个节点的内存地址,把这个记录下个结点地址的指针称为后继指针next

(2)第一个结点称为头结点,最后一个结点称为尾结点。尾结点的指针不是指向下一个结点,而是指向一个空地址NULL,表示这是链表的最后一个结点。

(3)链表插入、删除的时间复杂度O1),只需要修改指针即可。

(4)链表随机访问的时间复杂度是On)。因为链表的内存空间是零散的,没法像数组那样通过简单的寻址公式实现随机访问,只能一个一个结点依次遍历,直到找到相应的结点。

4、循环链表

和单链表唯一的区别就在于尾结点,尾结点的指针指向头结点,而不是空地址。

  

 

 

5、双向链表

 

 

 

  (1)相比单链表,多了一个前驱指针,指向前一个结点

(三)练习题

1、单链表反转。 leetcode : 206

 1 # 迭代方式
 2 class ListNode:
 3     def __init__(self, x):
 4         self.val = x
 5         self.next = None
 6 
 7 class Solution:
 8     def reverseList(self, head: ListNode) -> ListNode:
 9         if head is None or head.next is None:
10             return head
11         prev_node = None
12         while head is not None:
13             next_node = head.next    # 备份下一结点的内存地址
14             head.next = prev_node    # 当前结点的指针指向前一结点(头结点指向None)
15             prev_node = head         # 更新前一结点的值。
16             head = next_node         # 设置当前结点为下一结点的地址
17         return prev_node
18 
19 if __name__ == "__main__":
20     l1 = ListNode(1)
21     l1.next = ListNode(2)
22     l1.next.next = ListNode(3)
23     l1.next.next.next = ListNode(4)
24     l1.next.next.next.next = ListNode(5)
25     rev_result = Solution().reverseList(l1)
26     for i in range(6):
27         if rev_result is not None:
28             print(rev_result.val)
29             rev_result = rev_result.next
30         else:
31             print(rev_result)
 1 # 递归方式
 2 class ListNode:
 3     def __init__(self, x):
 4         self.val = x
 5         self.next = None
 6 
 7 class Solution:
 8     def reverseList(self, head: ListNode) -> ListNode:
 9         if head is  None or head.next is None:
10             return head
11         next_node = self.reverseList(head.next)
12         head.next.next = head
13         head.next = None
14         return next_node
15 """
16   递归和迭代不同的是,递归从后向前,迭代从前往后
17    1、 head.val = 4
18     4.next.next = head, 实际就是5的指针指向结点4的内存地址
19     4.next = None  ,断开之前 4 -> 5 的指针
20    2、 head.val = 3
21      3.next.next = head, 实际就是4的指针指向结点3的内存地址
22      3.next = None , 断开之前 3 -> 4 的指针
23     ...
24    4: head.val = 1
25     1.next.next = head, 实际就是2的指针指向结点1的内存地址
26     1.next = None  ,头结点指向None
27 """
28 if __name__ == "__main__":
29     l1 = ListNode(1)
30     l1.next = ListNode(2)
31     l1.next.next = ListNode(3)
32     l1.next.next.next = ListNode(4)
33     l1.next.next.next.next = ListNode(5)
34     rev_result = Solution().reverseList(l1)
35     for i in range(6):
36         if rev_result is not None:
37             print(rev_result.val)
38             rev_result = rev_result.next
39         else:
40             print(rev_result)

2、链表中环的检测

 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服