[I0A]链表-单链表

链表,分为单链表,双链表,循环链表。只要掌握基本的单链表后面两种非常轻松就可以解决。

什么是单链表?

链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。

┌───┬───┐             ┌───┬───┐             ┌───┬───┐
│data │next │---> │data │next │--->│data │next │
└───┴───┘             └───┴───┘             └───┴───┘

data域--存放结点值的数据域
next域--存放结点的直接后继的地址(位置)的指针域(链域)


typedef struct node node;

struct node{
    int element;
    node* next;
};

typedef struct {
    node *head;
    int size;
}linked_list;


这是一个包含单链表的基本定义。

单链表的创建:

linked_list create_list(){
    node* n = create_node(INT_MIN);
    linked_list list = {n,0};
    return list;
}


node* create_node(int element){
    node* n = malloc(sizeof(node));
    n->element = element;
    n->next = NULL;
    return n;
}

这是一个包含空头结点的单链表,之所以包含空头结点 是为了简化操作。


主要讲解,单链表的删除和插入过程,因为该两种过程是所有操作的基础。

删除:


插入:








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

typedef struct node node;

struct node{
    int element;
    node* next;
};

typedef struct {
    node *head;
    int size;
}linked_list;

node*
create_node(int element);

linked_list
create_list();

void
append(linked_list* list,int element);

node*
search(linked_list list,int element);

void
sort(linked_list* list);

void
print_list(linked_list list);

void
menu();

void
list_test();

void
clear_list(linked_list* list);

void 
delete(linked_list* list,int element);

node* 
find_less_than(linked_list list,int element);

int main(int argc,char** argv){
    list_test();
    return 0;
}

void delete(linked_list* list,int element){
	node *ptr = search(*list,element);
	//node *ptr = list->head;
    //while(ptr->next && ptr->next->element != element) ptr = ptr->next;
    if(ptr->next){
    	node* tmp = ptr->next;
    	ptr->next = ptr->next->next;
    	free(tmp);
    	list->size--;
    }
}

void clear_list(linked_list* list){
    node *n = list->head;
    while(n){
        list->head = n->next;
        free(n);
        n = list->head;
    }
    
}

void list_test(){
    linked_list list = create_list();
    int element,choice;
    while(1){
        menu();
        print_list(list);
        printf("input choice:");
        scanf("%d",&choice);
        switch(choice) {
            case 1:{printf("input number:");scanf("%d",&element);append(&list,element);break;}
            case 2:{printf("input number:");scanf("%d",&element);node *n = search(list,element);if(n->next) printf("element exists\n");break;}
            case 3:{sort(&list);break;}
            case 4:{printf("input number:");scanf("%d",&element);delete(&list,element);break;}
            case 5:{clear_list(&list);exit(0);}
            default:break;
        }
        getchar();
    }
}

node* find_less_than(linked_list list,int element){
	node *ptr = list.head;
	while(ptr->next && ptr->next->element < element) ptr = ptr->next;
	return ptr;
}

void menu(){
    system("clear");
    printf("Linked List Test\n");
    printf("1.append\n");
    printf("2.search\n");
    printf("3.sort\n");
    printf("4.delete\n");
    printf("5.exit\n");
}

void print_list(linked_list list){
    node* n = list.head->next;
    while(n){
        printf("%d\t",n->element);
        n = n->next;
    }
    printf("\n");
}

void sort(linked_list *list){
    node *ptr = list->head->next;
    list->head->next = NULL;
    while(ptr){
        node* n = ptr;
        node *tmp = find_less_than(*list,n->element);
        ptr = ptr->next;
        n->next = tmp->next;
        tmp->next = n;
    }
}


node* search(linked_list list,int element){
    node *ptr = list.head;
    while(ptr->next && ptr->next->element != element) ptr = ptr->next;
    return ptr;
}

void append(linked_list* list,int element){
    node *ptr = list->head;
    while(ptr->next!=NULL) ptr = ptr->next;
    ptr->next = create_node(element);
    list->size++;
}


linked_list create_list(){
    node* n = create_node(INT_MIN);
    linked_list list = {n,0};
    return list;
}


node* create_node(int element){
    node* n = malloc(sizeof(node));
    n->element = element;
    n->next = NULL;
    return n;
}



<think>我们正在讨论线性表的类型定义、顺序表示和实现、链式表示和实现,以及一元多项式的表示和相加应用。根据用户提供的引用,我们可以知道线性表在存储多项式时的应用,以及两种存储结构(顺序和链式)在不同运算中的适用性。同时,用户希望了解线性表的定义、基本操作、特点和应用。 我将按照以下结构组织回答: 1. 线性表的类型定义 2. 顺序表示与实现 2.1 定义 2.2 基本操作(初始化、插入、删除、查找等) 2.3 特点 3. 链式表示与实现 3.1 定义(单链表、双向链表、循环链表等) 3.2 基本操作(创建、插入、删除、查找等) 3.3 特点 4. 线性表的应用:一元多项式的表示与相加(结合引用[1][2][3][4]) 4.1 一元多项式的表示(顺序和链式) 4.2 一元多项式的相加(链式实现示例) 注意:在回答中,我们将使用LaTeX格式表示数学公式,代码块使用指定语言,并按照要求添加引用标识。 开始回答: </think>### 线性表的类型定义、表示与实现 #### 1. 线性表的类型定义 **定义**:线性表是由 $n$($n \geq 0$)个**相同数据类型**的元素构成的有限序列,记作: $$(a_1, a_2, \dots, a_n)$$ 其中 $a_i$ 是元素,$n$ 为表长。当 $n=0$ 时称为空表[^1]。 **逻辑特性**: - 存在唯一**首元素** $a_1$ 和**尾元素** $a_n$ - $a_i$ 的直接前驱是 $a_{i-1}$($i>1$) - $a_i$ 的直接后继是 $a_{i+1}$($i<n$) **抽象数据类型定义**(ADT): ```c ADT List { 数据对象:D = {a_i | a_i ∈ ElemType, i=1,2,...,n} 数据关系:R = {<a_{i-1}, a_i> | a_{i-1}, a_i ∈ D} 基本操作: InitList(&L) // 初始化 DestroyList(&L) // 销毁 ListInsert(&L, i, e) // 在位置i插入元素e ListDelete(&L, i, &e) // 删除位置i的元素 LocateElem(L, e) // 查找元素e的位置 ... } ``` --- ### 2. 顺序表示与实现 #### 定义 采用**连续存储空间**存放元素,逻辑上相邻的元素物理位置也相邻: $$ \text{Loc}(a_i) = \text{Loc}(a_1) + (i-1) \times c $$ 其中 $c$ 为元素大小[^1]。 **C语言实现**: ```c #define MAXSIZE 100 typedef struct { ElemType data[MAXSIZE]; // 静态分配 int length; // 当前长度 } SqList; ``` #### 基本操作 **插入操作**: ```c Status ListInsert(SqList &L, int i, ElemType e) { if (i < 1 || i > L.length+1) return ERROR; // 位置非法 if (L.length >= MAXSIZE) return ERROR; // 空间满 for (int j = L.length; j >= i; j--) // 元素后移 L.data[j] = L.data[j-1]; L.data[i-1] = e; L.length++; return OK; } ``` **时间复杂度**: - 最好 $O(1)$(尾部插入) - 最坏 $O(n)$(头部插入) - 平均 $O(n)$ **删除操作**: ```c Status ListDelete(SqList &L, int i, ElemType &e) { if (i < 1 || i > L.length) return ERROR; e = L.data[i-1]; for (int j = i; j < L.length; j++) // 元素前移 L.data[j-1] = L.data[j]; L.length--; return OK; } ``` **时间复杂度**:$O(n)$ #### 特点 | 优点 | 缺点 | |------|------| | 随机访问 $O(1)$ | 插入/删除效率低 $O(n)$ | | 存储密度高 | 需预估最大长度 | | 缓存友好 | 扩容代价高 | --- ### 3. 链式表示与实现 #### 定义 通过**指针**链接的节点序列,节点结构: ```c typedef struct LNode { ElemType data; // 数据域 struct LNode *next; // 指针域 } LNode, *LinkList; ``` #### 基本操作 **头插法创建链表**: ```c void CreateList_H(LinkList &L, int n) { L = (LinkList)malloc(sizeof(LNode)); L->next = NULL; // 创建头结点 for (int i = 0; i < n; i++) { LNode *p = (LNode*)malloc(sizeof(LNode)); scanf("%d", &p->data); p->next = L->next; // 新节点指向原首元节点 L->next = p; // 头结点指向新节点 } } ``` **指定位置插入**: ```c Status ListInsert(LinkList &L, int i, ElemType e) { LNode *p = L; int j = 0; while (p && j < i-1) { // 定位到第i-1个节点 p = p->next; j++; } if (!p || j > i-1) return ERROR; LNode *s = (LNode*)malloc(sizeof(LNode)); s->data = e; s->next = p->next; // 新节点指向原后继 p->next = s; // 原前驱指向新节点 return OK; } ``` **时间复杂度**:$O(n)$(查找)+ $O(1)$(插入) #### 特点 | 优点 | 缺点 | |------|------| | 动态内存分配 | 存储密度低 | | 插入/删除 $O(1)$ | 不支持随机访问 | | 无需预知规模 | 指针消耗额外空间 | --- ### 4. 一元多项式表示与相加应用 #### 表示方法 **链式存储结构**(解决指数差异大问题): ```c typedef struct PolyNode { float coef; // 系数 int expn; // 指数 struct PolyNode *next; } PolyNode, *Polynomial; ``` 示例多项式 $3x^5 + 2x^2 - 6$ 的存储: ```mermaid graph LR A[头结点] --> B[3|5] --> C[2|2] --> D[-6|0] --> NULL ``` #### 多项式相加算法 ```c void AddPolyn(Polynomial &Pa, Polynomial &Pb) { Polynomial p = Pa->next, q = Pb->next; Polynomial pre = Pa; // 指向p的前驱 while (p && q) { if (p->expn < q->expn) { // Pa节点指数小 pre = p; p = p->next; } else if (p->expn > q->expn) { // 插入Pb节点 Polynomial s = (Polynomial)malloc(sizeof(PolyNode)); *s = *q; // 复制节点 s->next = p; pre->next = s; pre = s; q = q->next; } else { // 指数相等 p->coef += q->coef; if (fabs(p->coef) < 1e-6) { // 系数和为0 pre->next = p->next; free(p); p = pre->next; } else { pre = p; p = p->next; } Polynomial tmp = q; q = q->next; free(tmp); } } if (q) pre->next = q; // 链接剩余项 free(Pb); } ``` **算法分析**: - **时间复杂度**:$O(m+n)$($m,n$ 为多项式项数) - **空间复杂度**:$O(1)$(原地合并) ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值