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


Posted in Python onJune 27, 2019

=一、链表

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

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

二、单链表介绍

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

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

三、单链表结构

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

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

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

1、头插

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

2、尾插

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

3、指定为之插入

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

4、删除

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

五、单链表的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 = num
def 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 相关文章推荐
vc6编写python扩展的方法分享
Jan 17 Python
python BeautifulSoup设置页面编码的方法
Apr 03 Python
使用Python脚本来获取Cisco设备信息的示例
May 04 Python
Python批量按比例缩小图片脚本分享
May 21 Python
Numpy数组转置的两种实现方法
Apr 17 Python
对python中的 os.mkdir和os.mkdirs详解
Oct 16 Python
Python使用sqlalchemy模块连接数据库操作示例
Mar 13 Python
使用django和vue进行数据交互的方法步骤
Nov 11 Python
Python Opencv 通过轨迹(跟踪)栏实现更改整张图像的背景颜色
Mar 09 Python
Tensorflow中的图(tf.Graph)和会话(tf.Session)的实现
Apr 22 Python
最新版 Windows10上安装Python 3.8.5的步骤详解
Nov 28 Python
python绘图模块之利用turtle画图
Feb 12 Python
python多线程并发实例及其优化
Jun 27 #Python
int在python中的含义以及用法
Jun 27 #Python
Pycharm运行加载文本出现错误的解决方法
Jun 27 #Python
基于python-opencv3的图像显示和保存操作
Jun 27 #Python
pycharm new project变成灰色的解决方法
Jun 27 #Python
python之mock模块基本使用方法详解
Jun 27 #Python
python文件选择对话框的操作方法
Jun 27 #Python
You might like
php判断表是否存在的方法
2015/06/18 PHP
php判断邮箱地址是否存在的方法
2016/02/13 PHP
JavaScript 闭包深入理解(closure)
2009/05/27 Javascript
javascript操作cookie的文章(设置,删除cookies)
2010/04/01 Javascript
JS分割字符串并放入数组的函数
2011/07/04 Javascript
jquery让返回的内容显示在特定div里(代码少而精悍)
2014/06/23 Javascript
javascript实现的右下角弹窗实例
2015/04/24 Javascript
基于jQuery实现Div窗口震动特效代码-代码简单
2015/08/28 Javascript
jQuery实现宽屏图片轮播实例教程
2015/11/24 Javascript
jQuery事件的绑定、触发、及监听方法简单说明
2016/05/10 Javascript
artDialog+plupload实现多文件上传
2016/07/19 Javascript
js修改onclick动作的四种方法(推荐)
2016/08/18 Javascript
关于Javascript中document.cookie的使用
2017/03/08 Javascript
Node+Express+MongoDB实现登录注册功能实例
2017/04/23 Javascript
详解node-ccap模块生成captcha验证码
2017/07/01 Javascript
JavaScript callback回调函数用法实例分析
2018/05/08 Javascript
在vue项目中正确使用iconfont的方法
2018/09/28 Javascript
node.js使用express框架进行文件上传详解
2019/03/03 Javascript
Vue中import from的来源及省略后缀与加载文件夹问题
2020/02/09 Javascript
jQuery 函数实例分析【函数声明、函数表达式、匿名函数等】
2020/05/19 jQuery
jQuery实现的分页插件完整示例
2020/05/26 jQuery
javascript实现评分功能
2020/06/24 Javascript
解决vue cli4升级sass-loader(v8)后报错问题
2020/07/30 Javascript
python2.7+selenium2实现淘宝滑块自动认证功能
2018/02/24 Python
Python subprocess模块功能与常见用法实例详解
2018/06/28 Python
Python3爬虫爬取英雄联盟高清桌面壁纸功能示例【基于Scrapy框架】
2018/12/05 Python
python占位符输入方式实例
2019/05/27 Python
python利用opencv实现SIFT特征提取与匹配
2020/03/05 Python
python中前缀运算符 *和 **的用法示例详解
2020/05/28 Python
澳大利亚珍珠首饰购物网站:Vayo Pearls
2019/03/11 全球购物
软件测试笔试题
2012/10/25 面试题
小学红领巾广播稿(3篇)
2014/09/13 职场文书
中学生勤俭节约倡议书
2015/04/29 职场文书
业务员管理制度范本
2015/08/06 职场文书
2016年感恩教师节活动总结
2016/04/01 职场文书
python绘制箱型图
2021/04/27 Python