侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

python算法与数据结构之单链表的实现代码

Python  /  管理员 发布于 7年前   146

=一、链表

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,操作复杂。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)和O(1)。

使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。链表最明显的好处就是,常规数组排列关联项目的方式可能不同于这些数据项目在记忆体或磁盘上顺序,数据的存取往往要在不同的排列顺序中转换。链表允许插入和移除表上任意位置上的节点,但是不允许随机存取。链表有很多种不同的类型:单向链表,双向链表以及循环链表。

二、单链表介绍

单向链表(单链表)是链表的一种,其特点是链表的链接方向是单向的,对链表的访问要通过顺序读取从头部开始。单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是以结点来表示的,每个结点的构成: 元素(数据元素的映象) + 指针(指示后继元素存储位置) ,元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。它的每个节点包含两个域, 一个信息域(元素域)和一个链接域 。这个链接指向链表中的下一个节点,而最后一个节点的链接域则指向一个空值。

链式存储结构的线性表将采用一组任意的存储单元存放线性表中的数据元素。由于不需要按顺序存储,链表在插入、删除数据元素时比顺序存储要快,但是在查找一个节点时则要比顺序存储要慢,使用链式存储可以克服顺序线性表需要预先知道数据大小的缺点,链表结构可以充分利用内存空间,实现灵活的内存动态管理。但是链式存储失去了数组随机存取的特点,同时增加了节点的指针域,空间开销较大。

三、单链表结构

  • 表元素域elem用来存放具体的数据。
  • 链接域next用来存放下一个节点的位置(python中的标识)
  • 变量p指向链表的头节点(首节点)的位置,从p出发能找到表中的任意节点。

四、单链表的常用操作图解

1、头插

2、尾插

3、指定为之插入

4、删除

五、单链表的python代码实现

# 创建节点class Node(object):  def __init__(self,item):    self.element = item    self.next = None# 创建单链表类class SingleLinkList(object):  def __init__(self):    self.header = None    self.length = 0  # 1、判断是否为空  def is_empty(self):    if self.header == None:      return True    else:      return False  # 2、头部插入  def add(self,node):    if self.is_empty():      self.header = node    else:      node.next = self.header      self.header = node      # currentNode = self.header    self.length += 1  # 3、尾部插入  def appent(self,node):    currentNode = self.header    if self.is_empty():      self.add(node)    else:      while (currentNode.next != None):        currentNode = currentNode.next      currentNode.next = node      self.length += 1  # 4、指定位置插入  def insert(self,node,index):    currentNode = self.header    if index>self.length+1 or index<=0:      print("你要插入的位置不对,请重现选择位置")    if index == 1:      self.add(node)    elif index == 2:      node.next = self.header.next      self.header.next = node      self.length += 1    else:      for i in range(1,index-1):        currentNode = currentNode.next      node.next = currentNode.next      currentNode.next = node      self.length += 1  # 5、遍历  def travel(self):    currentNode = self.header    if self.length == 0:      print("你要遍历的链表没有数据\n")    else:      print("你要遍历的链表里面的元素有:",end=" ")      for i in range(self.length):        print("%s "%currentNode.element,end=" ")        currentNode = currentNode.next      print("\n")  # 6、排序不用交换节点的位置,只需要交换节点上的数据值  def list_sort(self):    for i in range(0,self.length-1):      currentNode = self.header      for j in range(0,self.length-i-1):        if currentNode.element > currentNode.next.element:          temp = currentNode.element          currentNode.element = currentNode.next.element          currentNode.next.element = temp        currentNode = currentNode.next  # 7、按索引删除  def remove(self,index):    if index<=0 or index>self.length:      print("你输入的下标不对,请重新输入")      return    else:      if index == 1:        self.header = self.header.next        currentNode = self.header      elif index == 2:        currentNode = self.header        currentNode.next = currentNode.next.next      else:        currentNode = self.header        for i in range(1,index-1):          currentNode = currentNode.next        currentNode.next = currentNode.next.next    self.length -= 1  # 8、查找是否包含,并返回下标  def isContain(self,num):    contain = 0    currentNode = self.header    for i in range(self.length):      if currentNode.element == num:        print("%d在链表中%d处\n"%(num,i))        contain = 1      currentNode = currentNode.next    if contain == 0:      print("%d不在链表中\n"%num)  # 9、根据下标找节点  def searchNodeByIndex(self,index):    currentNode = self.header    if index<=0 or index>self.length:      print("你输入的下标不对,请重新输入\n")      return 0    else:      for i in range(index-1):        currentNode = currentNode.next      return currentNode  # 10、根据下标修改节点的值  def modifyByIndex(self,index,num):    currentNode = self.header    if index<=0 or index>self.length:      print("你输入的下标不对,请重新输入\n")    else:      for i in range(index-1):        currentNode = currentNode.next      currentNode.element = numdef main():  # 创建一个节点对象  node1 = Node(1)  # 创建一个单链表对象  single_link_list = SingleLinkList()  print("验证空链表的遍历")  single_link_list.travel()  print("验证头插")  single_link_list.add(node1)  single_link_list.travel()  print("验证尾插")  node2 = Node(2)  single_link_list.appent(node2)  single_link_list.travel()  print("验证按位置插入")  node3 = Node(3)  single_link_list.insert(node3,1)  single_link_list.travel()  print("继续验证头插")  node4 = Node(5)  single_link_list.add(node4)  single_link_list.travel()  print("继续验证按位置插入")  node5 = Node(4)  single_link_list.insert(node5,4)  single_link_list.travel()  print("验证删除")  single_link_list.remove(3)  single_link_list.travel()  print("验证查找一个节点是否在链表中")  single_link_list.isContain(8)  print("验证按下标查找节点")  node = single_link_list.searchNodeByIndex(2)  print("第二个节点的值为:%s"%node.element)  print("\n验证排序")  single_link_list.list_sort()  single_link_list.travel()  print("验证修改")  single_link_list.modifyByIndex(2,10)  single_link_list.travel()if __name__ == '__main__':  main()

运行结果为:

验证空链表的遍历
你要遍历的链表没有数据

验证头插
你要遍历的链表里面的元素有: 1 

验证尾插
你要遍历的链表里面的元素有: 1  2 

验证按位置插入
你要遍历的链表里面的元素有: 3  1  2 

继续验证头插
你要遍历的链表里面的元素有: 5  3  1  2 

继续验证按位置插入
你要遍历的链表里面的元素有: 5  3  1  4  2 

验证删除
你要遍历的链表里面的元素有: 5  3  4  2 

验证查找一个节点是否在链表中
8不在链表中

验证按下标查找节点
第二个节点的值为:3

验证排序
你要遍历的链表里面的元素有: 2  3  4  5 

验证修改
你要遍历的链表里面的元素有: 2  10  4  5 

六、单链表的C语言代码实现

#include <stdio.h>typedef struct N{  int element;  struct N *next;}Node;// 1、创建节点Node *createNode(int num){  Node *node;  node = (Node *)malloc(sizeof(Node));  node->element = num;  node->next = NULL;  return node;}// 2、创建链表Node *createSingleLinkList(Node *node){  Node *head = node;  return head;}// 3、获取链表长度int getlength(Node *head){  if (head == NULL)  {    return 0;  }  int count = 1;  Node *current = head;  while (current->next != NULL)  {    count++;    current = current->next;  }  return count;}// 4、头部插入Node * add(Node *head, Node *node){  if(head == NULL)  {    head = node;    return head;  }  else  {    node->next = head;    head = node;    return head;  }}// 5、尾部插入Node * append(Node *head,Node *node){  Node *current = head;  if (current->next == NULL)  {    add(head, node);  }  else  {    int len = getlength(head);    for (int i = 0; i<len-1; i++)    {      current = current->next;    }    current->next = node;  }  return head;}// 6、按下标插入节点Node * insert(Node *head,Node *node,int index){  int len = getlength(head);  if (index<=0||index>len+1)  {    printf("你要插入的位置不对,请重现选择位置");  }  Node *current = head;  if (index == 1)  {    head = add(head, node);  }  else if (index == 2)  {    node->next = head->next;    head->next = node;  }  else  {    for (int i = 1; i<index-1; i++)    {      current = current->next;    }    node->next = current->next;    current->next = node;  }  return head;}// 7、遍历void travel(Node *head){  int len = getlength(head);  printf("len = %d\n",len);  Node *current = head;  if (len == 0)  {    printf("你要遍历的链表没有数据\n");  }  else  {    printf("你要遍历的链表里面的元素有: ");    for (int i = 0; i<len; i++)    {      printf("%d ",current->element);      current = current->next;    }    printf("\n");  }}// 8、根据索引删除Node * delect(Node *head,int index){  int len = getlength(head);  if (index<=0||index>len)  {    printf("你输入的下标不对,请重新输入");    return head;  }  else  {    if (index == 1)    {      head = head->next;    }    else if (index == 2)    {      head->next = head->next->next;    }    else    {      Node *current = head;      for (int i = 1; i<index-1; i++)      {        current = current->next;      }      current->next = current->next->next;    }  }  return head;}// 9、查找是否包含,并返回下标void isContain(Node *head,int num){  int contain = 0;  Node *current = head;  int len = getlength(head);  for (int i = 0; i<len; i++)  {    if (current->element == num)    {      printf("%d在链表中的%d处\n",num,i+1);      contain = 1;    }    current = current->next;  }  if (contain == 0)  {     printf("%d不在链表中\n",num);  }}// 10、根据下标找节点Node *searchByIndex(Node *head , int index){  int len = getlength(head);  Node *current = head;  if (index<=0||index>len)  {    printf("你输入的下标不对,请重新输入");    return head;  }  else  {    for (int i = 0; i<index-1; i++)    {      current = current->next;    }    return current;  }}// 11、根据下标修改节点的值void modifyByIndex(Node *head,int index,int num){  int len = getlength(head);  Node *current = head;  if (index<=0||index>len)  {    printf("你输入的下标不对,请重新输入");  }  else  {    for (int i = 0; i<index-1; i++)    {      current = current->next;    }    current->element = num;  }}int main(int argc, const char * argv[]){  printf("==========1、创建节点==========\n");  Node * node1 = createNode(1);  printf("==========2、创建单链表==========\n");  Node * head = createSingleLinkList(node1);  travel(head);  printf("==========3、验证头插==========\n");  Node *node2 = createNode(0);  head = add(head, node2);  travel(head);  Node *node3 = createNode(2);  head = add(head, node3);  travel(head);  printf("==========4、验证尾插==========\n");  Node *node4 = createNode(4);  head = append(head,node4);  travel(head);  Node *node5 = createNode(5);  head = append(head,node5);  travel(head);  printf("==========5、验证按下标插入==========\n");  Node *node6 = createNode(6);  head = insert(head, node6, 1);  travel(head);  printf("==========6、验证按下标删除==========\n");  head = delect(head, 2);  travel(head);  printf("==========7、验证是否包含==========\n");  isContain(head, 8);  printf("==========8、验证根据下标找节点==========\n");  Node *n = searchByIndex(head, 1);  printf("第一个节点是%d\n",n->element);  printf("==========9、验证根据下标修改==========\n");  modifyByIndex(head, 3, 9);
    travel(head);
    return 0;
}

运行结果为:

==========1、创建节点==========
==========2、创建单链表==========
len = 1
你要遍历的链表里面的元素有: 1
==========3、验证头插==========
len = 2
你要遍历的链表里面的元素有: 0 1
len = 3
你要遍历的链表里面的元素有: 2 0 1
==========4、验证尾插==========
len = 4
你要遍历的链表里面的元素有: 2 0 1 4
len = 5
你要遍历的链表里面的元素有: 2 0 1 4 5
==========5、验证按下标插入==========
len = 6
你要遍历的链表里面的元素有: 6 2 0 1 4 5
==========6、验证按下标删除==========
len = 5
你要遍历的链表里面的元素有: 6 0 1 4 5
==========7、验证是否包含==========
8不在链表中
==========8、验证根据下标找节点==========
第一个节点是6
==========9、验证根据下标修改==========
len = 5
你要遍历的链表里面的元素有: 6 0 9 4 5

总结

以上所述是小编给大家介绍的python算法与数据结构之单链表的实现代码 ,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!


  • 上一条:
    选择python进行数据分析的理由和优势
    下一条:
    python多线程并发实例及其优化
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 在python语言中Flask框架的学习及简单功能示例(0个评论)
    • 在Python语言中实现GUI全屏倒计时代码示例(0个评论)
    • Python + zipfile库实现zip文件解压自动化脚本示例(0个评论)
    • python爬虫BeautifulSoup快速抓取网站图片(1个评论)
    • vscode 配置 python3开发环境的方法(0个评论)
    • 近期文章
    • 智能合约Solidity学习CryptoZombie第四课:僵尸作战系统(0个评论)
    • 智能合约Solidity学习CryptoZombie第三课:组建僵尸军队(高级Solidity理论)(0个评论)
    • 智能合约Solidity学习CryptoZombie第二课:让你的僵尸猎食(0个评论)
    • 智能合约Solidity学习CryptoZombie第一课:生成一只你的僵尸(0个评论)
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2018-04
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2022-01
    • 2023-07
    • 2023-10
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客