C指针实现单链表,主函数调用

C指针实现单链表,主函数调用

使用数组或者指针简单实现的表都有其不同的优缺点,例如数组的比较方便查询,不方便修改,指针的比较方便修改但不方便查询,同时需要额外空间存放指针……之后会有一种 间接寻址方法实现表 结合了以上两种方式的优点。

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

typedef int ListItem;     // 表元素类型
typedef ListItem *addr;   // 表元素指针类型
#define eq(A, B) (A == B) // 元素相等

typedef struct node *link; // 表结点指针类型
typedef struct node
{
    
    
    ListItem element; // 表元素
    link next;        // 指向下一个结点的指针域
} Node;

link NewNode() // 新建一个结点
{
    
    
    return (link)malloc(sizeof(Node));
}

typedef struct llist *List; // 单链表指针
typedef struct llist        // 单链表
{
    
    
    link first, // 链表首指针
        curr,   // 当前结点指针
        last;   // 表尾指针
} Llist;

List ListInit();                            // 表结构初始化,返回一个结构体指针
int ListEmpty(List L);                      // 测试表是否为空
int ListLength(List L);                     // 表L的长度
ListItem ListRetrieve(int k, List L);       // 返回表L位置k的元素
int ListLocate(ListItem x, List L);         // 元素x在表L的位置
void ListInsert(int k, ListItem x, List L); // 在表L索引k的位置插入元素x
ListItem ListDelete(int k, List L);         //从表L中删除位置k的元素
void PrintList(List L);                     // 按照位置次序输出表L中的元素
void ItemShow(ListItem x);                  // 输出表元素

int main(int argc, char const *argv[])
{
    
    
    List L = ListInit();
    puts("Init success.");
    link node_1 = NewNode();
    link node_2 = NewNode();
    link node_3 = NewNode();

    node_1->element = 11;
    node_2->element = 22;
    node_3->element = 33;

    L->first = node_1;
    node_1->next = node_2;
    node_2->next = node_3;
    node_3->next = 0;

    printf("list length is %d.\n", ListLength(L));

    PrintList(L);
    puts("---------------------");

    printf("22 locate is %d.\n", ListLocate(22, L));
    puts("---------------------");
    ListInsert(2, 44, L);
    puts("after ListInsert(2, 44, L); ");
    PrintList(L);
    puts("---------------------");

    ListItem delete_num = ListDelete(4, L);
    puts("after ListDelete(4, L) ");
    PrintList(L);
    puts("---------------------");

    free(L);
    puts("free success.");
    return 0;
}

void ItemShow(ListItem x) // 输出表元素
{
    
    
    printf("%d \n", x);
}

List ListInit() // 单链表结构初始化,返回一个结构体指针
{
    
    
    List L = (List)malloc(sizeof *L);
    L->first = 0;
    return L;
}

int ListEmpty(List L) // 测试表是否为空
{
    
    
    return L->first == 0;
}

int ListLength(List L) // 遍历链表所有元素计算长度
{
    
    
    int len = 0;       // 记录表长度,作为返回
    link p = L->first; // p为链表首结点
    while (p)
    {
    
    
        len++;
        p = p->next;
    }
    return len;
}

ListItem ListRetrieve(int k, List L) // 返回表L位置k的结点的值
{
    
    
    if (k < 1)
        return 0;
    link p = L->first;
    int i = 1; // 从1开始遍历链表
    while (i < k && p)
    {
    
    
        p = p->next;
        i++;
    }
    return p->element;
}

int ListLocate(ListItem x, List L) // 结点x在表L的位置
{
    
    
    int i = 1;
    link p = L->first;
    while (p && p->element != x)
    {
    
    
        p = p->next;
        i++;
    }
    return p ? i : 0; // 若结点值存在返回其位置i,不存在返回0
}

void ListInsert(int k, ListItem x, List L) // 在表L索引k的位置插入结点值为x的结点
{
    
    
    if (k < 0)
        return;
    link p = L->first;
    for (int i = 1; i < k && p; i++) // 先遍历到位置k
        p = p->next;
    link y = NewNode(); // 新建一个结点,赋值为x
    y->element = x;
    if (k) // 若位置k存在,将y的next指向k的next;位置k的next指向y
    {
    
    
        y->next = p->next;
        p->next = y;
    }
    else // 遍历不到,就添加到表头
    {
    
    
        y->next = L->first;
        L->first = y;
    }
}

ListItem ListDelete(int k, List L) //从表L中删除位置k的元素
{
    
    
    if (k < 1 || !L->first) // 删除不合法
        return 0;
    link p = L->first; // 表头结点 p
    if (k == 1)        // 删除表头,
        L->first = p->next;
    else // 删除表中间
    {
    
    
        link q = L->first;                   // p q 两个都是表头结点,p是辅助的,q用来删除结点,删除相当于直接跳过这个结点,将next指针指向下下个结点
        for (int i = 1; i < k - 1 && q; i++) // 先遍历到k
            q = q->next;
        p = q->next;
        q->next = p->next;
    }
    ListItem x = p->element; // 用作返回的被删除结点的值
    free(p);
    return x;
}

void PrintList(List L) // 按照位置次序输出表L中的元素
{
    
    
    for (link p = L->first; p; p = p->next)
    {
    
    
        ItemShow(p->element);
    }
}

result:

Init success.
list length is 3.
11
22
33
---------------------
22 locate is 2.
---------------------
after ListInsert(2, 44, L);
11
22
44
33
---------------------
after ListDelete(4, L)
11
22
44
---------------------
free success.

猜你喜欢

转载自blog.csdn.net/qq_44880154/article/details/113555204