python算法与数据结构-循环链表(41)

一、循环链表的介绍

  上一篇我们已经讲过单链表,本篇给大家讲解循单链表的一个变形是单向循环链表,链表中最后一个节点的next域不再为None,而是指向链表的头节点,其基本操作和单链表思路一样。

常用的操作有

  1. 创建节点
  2. 创建循环链表
  3. 判断是否为空
  4. 头部插入
  5. 循环链表的遍历
  6. 尾部插入
  7. 获取链表长度
  8. 根据下标插入一个节点
  9. 根据下标删除一个节点
  10. 查找是否包含一个节点,并返回其在链表中的位置
  11. 根据下标找节点
  12. 根据下标修改节点的值
  13. 对链表排序

二、循环链表基本操作的python代码实现

class Node():
    def __init__(self,num):
        self.element = num
        self.next = None
        
class CricleLinkList(object):
    def __init__(self):
        self.head = None
        self.length = 0

    # 1、判断是否为空
    def is_empty(self):
        if self.head == None:
            return True
        else:
            return False
    
    # 2、头部插入
    def add(self, num):
        # 创建要插入的节点
        node = Node(num)
        if self.is_empty()==True:
            # 如果为空直接插入
            self.head = node
            # 并且把自身的next执行头结点
            node.next = self.head
        else:
            # 将原来的头结点作为插入节点的next
            node.next = self.head
            current = self.head
            # 循坏找到最后一个节点
            while current.next != self.head:
                current = current.next
            # 将最后一个节点的next执行插入节点
            current.next = node
            # 将插入的节点设置为头结点,完成循坏闭合
            self.head = node
        # 每次添加完成一次,长度加1
        self.length += 1

    # 3、遍历
    def travel(self):
        if self.is_empty() == True:
            print("你要遍历的循环链表为空")
            return
        
        print("你要遍历的循环链表元素有:", end=" ")
        current = self.head
        # 先把第一个元素打印一下
        print("%d " % current.element, end=" ")
        # 打印只有一个元素的时候,第一个元素打印不出来,所以先把第一个打印出来
        while current.next != self.head:
            
            current = current.next
            print("%d " % current.element, end=" ")
        print("")
                
    # 4、尾部插入
    def append(self,num):
        node = Node(num)
        if self.is_empty() == True:
            self.add(num)
        else:
            current = self.head
            while current.next != self.head:
                current = current.next
            node.next = self.head
            current.next = node
        # 每次添加完成一次,长度加1
        self.length += 1
            
    # 5、指定位置插入
    def insertAtIndex(self,num,index):
        if index<=0 or index>self.length+1:
            print("你要插入的位置不对,请重新选择位置")
            return
        elif self.is_empty() == True:
            self.add(num)
        elif index==1:
            self.add(num)
        elif index == self.length+1:
            self.append(num)
        else:
            current = self.head
            for i in range(index-2):
                current = current.next
            node = Node(num)
            node.next = current.next
            current.next = node
            
        # 每次添加完成一次,长度加1
        self.length += 1

    # 6、按索引删除
    def deleteByIndex(self,index):
        
        if index<=0 or index>self.length:
            print("你要插入的位置不对,请重新选择位置")
            return
        elif self.is_empty() == True:
            print("你要删除的链表为空")
            return
        elif index == 1:
            current = self.head
            for i in range(1,self.length):
                current = current.next
            current.next = self.head.next
            self.head = self.head.next
        else:
            current = self.head
            for i in range(index-2):
                current = current.next
            current.next = current.next.next
        # 每次删完长度减1
        self.length -= 1

    # 7、查找是否包含,并返回位置
    def isContain(self,num):
        if self.is_empty() == True:
            print("你要查询的链表为空")
            return
        else:
            current = self.head
            for i in range(self.length):
                if current.element == num:
                    print("你要找到元素在第%d个节点"%(i+1))
                    return i+1
                current = current.next
            print("没有找到你要的元素")
        return -1
    
    # 8、根据下标找节点
    def searchNodeByIndex(self,index):
        if index<=0 or index>self.length:
            print("你要查询的位置不对,请重新选择位置")
            return
        elif self.is_empty() == True:
            print("你要查询的链表为空")
        else:
            current = self.head
            for i in range(1,index):
                current = current.next
            print("你要查找%d位置上的节点的值是%d"%(index,current.element))
            
    # 9、根据下标修改节点的值
    def modifyByIndex(self,index,num):
        if index <= 0 or index > self.length:
            print("你要查询的位置不对,请重新选择位置")
            return
        elif self.is_empty() == True:
            print("你要修改的链表为空")
        else:
            current = self.head
            for i in range(1, index):
                current = current.next
            current.element = num
            
    # 10、排序
    def sort(self):
        if self.length<=0:
            return
        for i in (0,self.length-1):
            current = self.head
            for j in range(0,self.length-i-1):
                if current.element>current.next.element:
                    temp = current.element
                    current.element = current.next.element
                    current.next.element = temp
                current = current.next
        
            
if __name__ == '__main__':
    
    print("======1、创建循环链表 ======")
    cricle_link_list = CricleLinkList()

    print("======2、验证是否为空 ======")
    empty = cricle_link_list.is_empty()
    if empty == True:
        print("你查询的链表为空")
    else:
        print("你查询的链表不为空")
    
    print("\n======3、验证头插和遍历 ======")
    cricle_link_list.add(1)
    cricle_link_list.travel()
    
    print("\n======4、继续验证头插和遍历 ======")
    cricle_link_list.add(2)
    cricle_link_list.travel()
    
    print("\n======5、验证尾插 ======")
    cricle_link_list.append(3)
    cricle_link_list.travel()
    
    print("\n======6、验证按位置插入 ======")
    cricle_link_list.insertAtIndex(0,2)
    cricle_link_list.travel()
    
    print("\n======7、验证按位置删除 ======")
    cricle_link_list.deleteByIndex(5)
    cricle_link_list.travel()
    
    print("\n======8、验证查找是否包含元素 ======")
    cricle_link_list.isContain(2)
    
    print("\n======9、验证根据下标查找元素 ======")
    cricle_link_list.searchNodeByIndex(3)
    
    print("\n======10、验证修改 ======")
    cricle_link_list.modifyByIndex(3,5)
    cricle_link_list.travel()
    
    print("\n======11、验证排序 ======")
    cricle_link_list.sort()
    cricle_link_list.travel()
    

运行结果为:

======1、创建循环链表 ======
======2、验证是否为空 ======
你查询的链表为空

======3、验证头插和遍历 ======
你要遍历的循环链表元素有: 1  

======4、继续验证头插和遍历 ======
你要遍历的循环链表元素有: 2  1  

======5、验证尾插 ======
你要遍历的循环链表元素有: 2  1  3  

======6、验证按位置插入 ======
你要遍历的循环链表元素有: 2  0  1  3  

======7、验证按位置删除 ======
你要插入的位置不对,请重新选择位置
你要遍历的循环链表元素有: 2  0  1  3  

======8、验证查找是否包含元素 ======
你要找到元素在第1个节点

======9、验证根据下标查找元素 ======
你要查找3位置上的节点的值是1

======10、验证修改 ======
你要遍历的循环链表元素有: 2  0  5  3  

======11、验证排序 ======
你要遍历的循环链表元素有: 0  2  3  5  

三、循环链表基本操作的C语言实现

//
//  main.m
//  循环链表
//
//  Created by 侯垒 on 2019/6/27.
//  Copyright © 2019 可爱的侯老师. All rights reserved.
//

#include <stdio.h>
// 创建节点结构体
typedef struct N
{
    int element;
    struct N *next;
}Node;

// 1、创建节点
Node *createNode(int num)
{
    Node *node = (Node *)malloc(sizeof(Node));
    node->element = num;
    node->next = NULL;
    return node;
}

// 2、创建循环链表
Node *createCricleLinkList(int num)
{
    Node *head = createNode(num);
    head->next = head;
    return head;
}

// 3、判断是否为空
int is_empty(Node *head)
{
    if (head == NULL)
    {
        return 1;
    }
    return 0;
}

//4、头部插入
Node *add(Node *head,int num)
{
    Node* node = createNode(num);
    Node *current = head;
    if (is_empty(head)==1)
    {
        head = node;
        node->next = head;
    }
    else
    {
        node->next = head;
        while (current->next != head)
        {
            current = current->next;
        }
        current->next = node;
        head = node;
    }
    return head;
}

// 5、遍历
void travel(Node *head)
{
    if (is_empty(head) == 1)
    {
        printf("你遍历的链表为空\n");
    }
    else
    {
        printf("\n你要遍历的循环链表元素有:");
        Node *current = head;
        printf("%d ",current->element);
        while (current->next != head)
        {
            current = current->next;
            printf("%d ",current->element);
        }
        printf("\n");
    }
}

// 5、尾部插入
Node *append(Node *head,int num)
{
    Node *node = createNode(num);
    if (is_empty(head)==1)
    {
        add(head, num);
    }
    else
    {
        Node *current = head;
        while (current->next != head)
        {
            current = current->next;
        }
        node->next = head;
        current->next = node;
    }
    return head;
}

// 6、获取链表长度
int getLength(Node *head)
{
    int count = 1;
    Node *current = head;
    if (is_empty(head)==1)
    {
        return 0;
    }
    else
    {
        while (current->next !=head)
        {
            current = current->next;
            count++;
        }
        return count;
    }
}

// 7、根据下标插入节点
Node * insertByIndex(Node *head,int num,int index)
{
    int len = getLength(head);
    if (index<=0||index>len+1)
    {
        printf("你要插入的位置不对,请重新选择位置");
    }
    else if (index == 1)
    {
        head = add(head, num);
    }
    else
    {
        Node *current = head;
        for (int i=1; i<index-1; i++)
        {
            current = current->next;
        }
        Node *node = createNode(num);
        node->next = current->next;
        current->next = node;
    }
    return head;
}

// 8、根据下标删除
Node *deleteByIndex(Node *head,int index)
{
    int len = getLength(head);
    if (index<=0||index>len)
    {
        printf("\n你要删除的位置不对,请重新选择位置");
    }
    else if (index == 1)
    {
        Node *current = head;
        for (int i=1; i<len; i++)
        {
            current = current->next;
        }
        current->next = head->next;
        head = head->next;
    }
    else
    {
        Node *current = head;
        for (int i=0; i<index-2; i++)
        {
            current = current->next;
        }
        current->next = current->next->next;
    }
    return head;
}

// 9、查找是否包含,并返回位置
int isContain(Node *head,int num)
{
    int len = getLength(head);
    Node *current = head;
    for (int i= 0; i<len; i++)
    {
        if (current->element == num)
        {
            return i+1;
        }
        current=current->next;
    }
    return 0;
}

// 10、根据下标找节点
Node *searchNodeByIndex(Node *head,int index)
{
    Node *current = head;
    int len = getLength(head);
    if (index<=0||index>len)
    {
        printf("\n你要查询的位置不对,请重新选择位置");
    }
    else
    {
        
        for (int i =1 ; i<index; i++)
        {
            current = current->next;
        }
        printf("\n你要查找的%d位置上的值为%d",index,current->element);
    }
    return current;
}

// 11、根据下标修改节点的值
void modefyByIndex(Node *head,int index,int num)
{
    Node *current = head;
    int len = getLength(head);
    if (index<=0||index>len)
    {
        printf("\n你要修改的位置不对,请重新选择位置");
    }
    else
    {
        for (int i =1 ; i<index; i++)
        {
            current = current->next;
        }
        current->element = num;
    }
}

// 12、排序
void sort(Node *head)
{
    int len = getLength(head);
    if (len<=0)
    {
        return;
    }
    for (int i = 0; i<len-1; i++)
    {
        Node *current = head;
        for (int j=0; j<len-i-1; j++)
        {
            if (current->element >current->next->element)
            {
                int temp = current->element;
                current->element = current->next->element;
                current->next->element = temp;
            }
            current = current->next;
        }
    }
}

int main(int argc, const char * argv[])
{
    printf("=====1、创建循环链表=====");
    Node *head = createCricleLinkList(1);
    
    printf("\n=====2、验证是否为空=====\n");
    int empty = is_empty(head);
    if (empty == 1)
    {
        printf("你创建的循环链表为空");
    }
    else
    {
        printf("你创建的循环链表不为空");
    }
    
    printf("\n=====3、验证头插和遍历=====");
    travel(head);
    head =  add(head, 0);
    travel(head);
    
    printf("\n=====4、验证尾插=====");
    head = append(head, 2);
    travel(head);
    
    printf("\n=====5、验证根据下表插入=====");
    head = insertByIndex(head, 3, 2);
    travel(head);
    
    printf("\n=====6、验证根据下表删除=====");
    head = deleteByIndex(head, 3);
    travel(head);
    
    printf("\n=====7、验证是否包含=====");
    int num = 3;
    int index = isContain(head, num);
    if (index != 0)
    {
        printf("\n你查找的数据%d在第%d个位置",num,index);
    }
    else
    {
        printf("\n没有找到你要的数据\n");
    }
    
    printf("\n=====8、验证根据下标找节点=====");
    searchNodeByIndex(head, 2);
    printf("\n=====9、验证根据下标修改节点值=====");
    modefyByIndex(head,2,4);
    travel(head);
    
    printf("\n=====10、验证排序=====");
    sort(head);
    travel(head);
    
    return 0;
}

运行结果为:

=====1、创建循环链表=====
=====2、验证是否为空=====
你创建的循环链表不为空
=====3、验证头插和遍历=====
你要遍历的循环链表元素有:1 

你要遍历的循环链表元素有:0 1 

=====4、验证尾插=====
你要遍历的循环链表元素有:0 1 2 

=====5、验证根据下表插入=====
你要遍历的循环链表元素有:0 3 1 2 

=====6、验证根据下表删除=====
你要遍历的循环链表元素有:0 3 2 

=====7、验证是否包含=====
你查找的数据3在第2个位置
=====8、验证根据下标找节点=====
你要查找的2位置上的值为3
=====9、验证根据下标修改节点值=====
你要遍历的循环链表元素有:0 4 2 

=====10、验证排序=====
你要遍历的循环链表元素有:0 2 4 

 

posted @ 2019-06-27 22:14  Se7eN_HOU  阅读(574)  评论(0编辑  收藏  举报