The creation of static linked list and dynamic linked list is implemented using C language and python

Questions, create a linked list for the purpose of entering the scores and student numbers of three students

(1) C language (static linked list)

// 静态链表
/*
    所以的节点都是在程序中定义的,不是临时开辟的,
    也不能在用完后释放空间,这种称为静态链表
*/

# include <stdio.h>

// 声明结构体
struct Student
{
    
    
    long int num;
    float score;
    struct Student * next;  // next 指针
};

int main()
{
    
    
    // 定义结构体变量3个
    struct Student s1, s2, s3, * head, *p;
    // 数据赋值
    s1.num = 10101; s1.score = 89.5;
    s2.num = 10102; s2.score = 90;
    s3.num = 10103; s3.score = 85;
    // 头指针
    head = &s1;
    // next 指针
    s1.next = &s2; s2.next = &s3; s3.next = NULL;
    // p 指针用于循环遍历, 指向链表首元素
    p = head;
    
    // 循环输出
    do 
    {
    
    
        printf("%ld %5.1f\n", p->num, p->score);
        p = p->next;
    }while(p != NULL);
    printf("已打印完链表所有信息!\n");
    return 0;
}

(2) C language (dynamic linked list)

// 动态链表
/* 
    是指在程序中,从无到有的建立一个链表,
    既一个一个地开辟节点和输入各节点的数据,并建立起前后相连的关系。
*/


# include <stdio.h>
# include <stdlib.h>

// 先定义出来开辟空间大小,既结构体大小
# define  LEN sizeof(struct Student)

struct Student 
{
    
    
    long num;
    float score;
    struct Student * next;
};

int n = 0;

// 定义函数,返回head指针, 既返回指向链表头的指针
struct Student * create(void)
{
    
    
    struct Student *p1, *p2, *head;  // p1 表示下一个元素,p2 表示当前元素
    // 定义输入第一个节点数据
    p1 = p2 = (struct Student * )malloc(LEN);
    printf("请输入学生信息:\n");
    scanf("%d, %f", &p1->num, &p1->score);
    // 空链表。头指针为NULL
    head = NULL;

    // 默认输入数据 为0,结束输入
    while(p1->num != 0)
    {
    
    
        n += 1;
        if (n==1) head=p1;
        else p2->next=p1;

        p2 = p1;
        p1 = (struct Student * )malloc(LEN);
        printf("请输入学生信息\n");
        scanf("%d, %f", &p1->num, &p1->score);
    }
    p2->next = NULL;
    return head;
}

int main()
{
    
    
    struct Student * h;
    h = create();
    printf("num == %ld\n, score == %5.1f\n", h->num, h->score);
    return 0;
}


python implementation

  • For python, I use a dictionary to achieve
  • Very interesting, the data field is restricted, and the iterator loop output is added
  • It is also possible to transform the Node class into a singleton, I did not continue here~
# 因为字典的键可以是任意类型的,但是我们希望 键是 数值型的,整形或者浮点型,所以定义数据描述器限制

# 因为可能多个字段需要定义 约束 我们先设计一个外键约束的 基类,简化后续
class BaseField():

    def __init__(self, attrname):
        self.attrname = attrname

    def __get__(self, instance, owner):
        return getattr(instance, self.attrname)

    def __set__(self, instance, value):
        setattr(instance, self.attrname, value)

    def __delete__(self, instance):
        raise Exception('can not delete email')


import re
class NumField(BaseField):
    NUM_MOD = re.compile('^\d{4,6}$')

    def __set__(self, instance, value):
        if not self.NUM_MOD.match(value):
            raise Exception('请输入有效格式学号!')
        setattr(instance, self.attrname, value)


class ScoreField(BaseField):

    def __set__(self, instance, value):
        if not (0 <= value and  value <= 100):
            raise Exception('{}错误!成绩为 0-100,请重新输入!'.format(value))
        setattr(instance, self.attrname, value)


# 以 字典作为节点, 定义相关节点的操作
class Node():
    num = NumField("_num")
    score = ScoreField("_score")
    def __init__(self, num, score):
        self.num = num
        self.score = score
        self.node = {
    
    
            'num': '00001',
            'score': 0,
            'next': None
        }

# 定义链表
class lianbiao():
    # 类属性是 节点类 Node
    node = Node

    def __init__(self):
        self.head = None
        self.p1 = self.p2 = None
        # n 可表示 链表长度, 设置为私有属性,不允许外部更改
        self.__n = 0
        # 用来实现迭代器
        self.i = 1


    # 定义相关操作函数
    # 增加节点
    def create(self, num='00001', score=0, next=None):        
        self.__n += 1
        # 实例方法 访问类属性
        a = self.node(num, score)
        a.node['num'] = a.num
        a.node['score'] = a.score

        # 下面的逻辑和 C语言的是相同的
        self.p1 = a.node

        if self.__n == 1:
            self.head = self.p1
        else:
            self.p2['next'] = self.p1

        self.p2 = self.p1

    # 实现迭代器方便遍历
    def __iter__(self):
        # 每次调用迭代器 都要将这两个变量 初始化,因为循环一次后, i 值可能为 8, 下次还会从8开始! 包括p1,同理
        self.p1 = self.head
        self.i = 1
        return self

    def __next__(self):
        # 必须重新定义变量,若直接使用头指针,遍历结束将改变 头指针的指向
        if self.i == 1:
            self.i += 1
            return self.p1
        else:
            self.p1 = self.p1['next']
            if self.p1 != None:
                self.i += 1
                return self.p1
            else: 
                raise StopIteration

    # 输出数组长度, 定义为属性
    @property
    def length(self):
        return self.__n

lian = lianbiao()
# python 3.6 不支持表达式赋值
i = 1
while (i < 3):
    i += 1
    print("请输入数据: 学号5位数字组成, 成绩0-100分")
    a = input()
    b = input()
    b = int(b)
    lian.create(a, b)


# head = lian.head
# for i in range(lian.length):
#     print(head)
#     head = head['next']
#     if head == None:
#         break


# 生成迭代器后这样遍历
for i in lian:
    print(i)


Guess you like

Origin blog.csdn.net/pythonstrat/article/details/113182777