单向链表的实现

链表
链表是链式的存储多个元素 .
但不同于列表 , 链表中的元素在内存中不必是连续的空间
链表的每个元素由一个存储元素本身的节点和一个指向下一个元素的引用 ( 有些语言称为指针
或者链接 ) 组成
链表访问任何一个位置的元素时 , 都需要从头开始访问 .( 无法跳过第一个元素访问任何一个元
)
链表常见的操作
append(element) :向列表尾部添加一个新的项
insert(position, element) :向列表的特定位置插入一个新的项。
remove(element) :从列表中移除一项。
indexOf(element) :返回元素在链表中的索引。如果列表中没有该元素则返回 -1
removeAt(position) :从列表的特定位置移除一项。
isEmpty() :如果链表中不包含任何元素,返回 true ,如果链表长度大于 0 则返回 false
size() :返回链表包含的元素个数。与数组的 length 属性类似。
单向链表 :
只能从头遍历到尾或者从尾遍历到头 ( 一般从头到尾 )
也就是链表相连的过程是单向的 . 实现的原理是上一个链表中有一个指向下一个的引用 .
单向链表有一个比较明显的缺点 :
我们可以轻松的到达下一个节点 , 但是回到前一个节点是很难的
单向链表的实现
# 创建节点类,用于存放每个节点信息
class Node():
    def __init__(self, el):
        self.el = el
        self.next = None
# 创建链表类
class LinkedList():
    # 链表的类 初始化数据个数和头部节点
    def __init__(self):
        self.length = 0
        self.head = None
# 根据元素获取链表中的位置
    def indexof(self, el):
        # 定义变量, 保存信息
        current = self.head
        index = 0
        # 找到元素所在的位置
        while (current != None):
            if (current.el == el):
                return index
            index += 1
            current = current.next
        return -1 # 来到这个位置, 说明没有找到, 则返回-1
# 给链表尾部追加元素
    def append(self, el):
    # 根据传入的数据创建新节点
    newNode = Node(el)
    # 如果是空链表直接把头部节点指定为新节点
    if (self.head == None):
        self.head = newNode
    # 链表不为空
    else:
        # 定义变量,保存当前头部节点
        current = self.head
        # 循环找到链表中最后一个节点
        while (current.next != None):
            current = current.next
        # 把最后一个节点的next设置为新节点
        current.next = newNode
    self.length += 1 # 增加链表长度
# 根据下标插入节点
def insert(self, position, element):
# 检测越界问题: 越界插入失败
    if (position < 0 or position > self.length):
        return False
    # 定义变量, 保存信息
    newNode = Node(element)
    current = self.head
    previous = None
    index = 0
    if (position == 0):
        newNode.next = current
        self.head = newNode
    else:
        while (index < position):
            previous = current
            current = current.next
            index += 1
        newNode.next = current
        previous.next = newNode
    self.length += 1
        return True
def removeAt(self, position):
    # 检测越界问题: 越界移除失败, 返回None
    if (position < 0 or position >= self.length):
        return None
    # 定义变量, 保存信息
    current = self.head
    previous = None
    index = 0
    # 判断是否是移除第一项
    if (position == 0):
        self.head = current.next
    else:
        while (index < position):
            previous = current
            current = current.next
            index += 1
        previous.next = current.next
    self.length -= 1
    return current.el
# 根据元素删除信息
def remove(self, el):
    index = self.indexof(el)
    return self.removeAt(index)
# 判断链表是否为空
def isEmpty(self):
    return self.length == 0
# 获取链表的长度
def size(self):
    return self.length



list1 = LinkedList()
for i in range(6):
list1.append(i)
print(list1.indexof("hello")) # -1
print(list1.indexof(4)) # 4
print(list1.remove(4)) # 4
print(list1.size()) # 5

  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
约瑟夫问题是一个经典的数学问题,它的具体描述是:有n个人围成一圈,从第k个人开始报数,报到m的人出列,然后从下一个人开始重新报数,直到所有人都出列。现在我来介绍一下如何使用C语言的单向链表实现约瑟夫问题。 首先,我们需要定义一个链表节点的结构体,包含两个成员变量:一个是保存人员编号的整型变量,另一个是指向下一个节点的指针。 ```c typedef struct Node { int data; struct Node* next; } Node; ``` 接下来,我们可以编写一个函数来创建一个包含n个节点的循环链表,并返回链表的头节点。 ```c Node* createCircularLinkedList(int n) { Node* head = NULL; Node* prev = NULL; for (int i = 1; i <= n; i++) { Node* newNode = (Node*)malloc(sizeof(Node)); newNode->data = i; if (head == NULL) { head = newNode; } else { prev->next = newNode; } prev = newNode; } prev->next = head; // 将最后一个节点的next指针指向头节点,形成循环链表 return head; } ``` 接下来,我们可以编写一个函数来模拟约瑟夫问题的求解过程。 ```c void josephusProblem(Node* head, int k, int m) { Node* current = head; Node* prev = NULL; // 找到从第k个人开始报数的节点 for (int i = 1; i < k; i++) { prev = current; current = current->next; } // 开始报数并出列,直到所有人都出列 while (current->next != current) { // 报数m次 for (int i = 1; i < m; i++) { prev = current; current = current->next; } // 出列 prev->next = current->next; Node* temp = current; current = current->next; free(temp); } // 输出最后一个出列的人员编号 printf("最后一个出列的人员编号:%d\n", current->data); // 释放头节点的内存 free(current); } ``` 最后,我们可以在主函数中调用上述函数来解决约瑟夫问题。 ```c int main() { int n, k, m; printf("请输入总人数n:"); scanf("%d", &n); printf("请输入从第k个人开始报数:"); scanf("%d", &k); printf("请输入报数m次出列:"); scanf("%d", &m); Node* head = createCircularLinkedList(n); josephusProblem(head, k, m); return 0; } ``` 这样,我们就可以通过C语言的单向链表实现约瑟夫问题了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值