单链表的构造及其功能

定义

线性表的链式存储又称单链表,它是指通过一组任意的存储单元来存储线性表中的数据元素。为了建立数据元素之间的线性关系,对每个链表节点,除存放元素自身的信息外,还需要存放一个指向其后继的指针。

单链表的优缺点
优点
1、增加、删除元素方便,不用大量移动元素
2、不需要空间提前开辟,易扩充
缺点
1、不支持随机存储
2、开辟了指针域,会浪费额外的空间

单链表的初始化

LinkList InitList(){ //初始化
    LinkList L = (LinkList)malloc(sizeof(LNode)); //C开辟动态内存
    //L = new (LNode);  //C++开辟动态内存
    if (L == NULL){
        return NULL;    //内存不足,分配失败
    }
    L->next = NULL; //将L的指针域设为空
    return L;
}

单链表的头插法的构建

优点:可用于链表的逆置

LinkList List_Front_Insert(LinkList L){ //初始化头插
    printf("请输入数据(-1结束):");  //连续输入数据,-1结束
    int n;
    LNode* newNode;  //新节点

    scanf("%d", &n);

    while (n != -1){
        newNode = (LNode*)malloc(sizeof(LNode));  //为新节点开辟空间
        newNode->data = n;
        newNode->next = L->next;
        L->next = newNode;

        scanf("%d", &n);
    }
    return L;
}

单链表的尾插法的构建

LinkList List_Tail_Insert(LinkList L){ //初始化尾插
    printf("请输入数据(-1结束):");
    int n;
    LNode* newNode;  //新节点
    LNode* tail = L; //尾结点

    scanf("%d", &n);
    while ( n!=-1 ){
        newNode = (LNode*)malloc(sizeof(LNode)); //为新节点开辟空间
        newNode->data = n;
        tail->next = newNode;
        tail = newNode;
        
        scanf("%d", &n);
    }
    tail->next = NULL;  //尾结点指向空,很重要
    return L;
}

单链表的查找操作

从单链表的第一个结点开始,由前往后依次比较表中各节点数据域的值,若某结点数据域的值等于给定值elem,则返回该节点的指针;否则该链表中没有该元素,返回NULL。
LNode* LocatElem(LinkList L, ElemType elem){ //查找
    LNode* p = L->next;
    while (p != NULL && p->data != elem){
        p = p->next;
    }
    return p;  //返回该结点
}

单链表的插入操作

LinkList ListInsert(LinkList L, int index, ElemType elem){ //插入
    LNode* newNode = (LNode*)malloc(sizeof(LNode));
    newNode->data = elem;  //待插入的结点

    if (index == 1){  //类似头插
        newNode->next = L->next;
        L->next = newNode;
        return L;
    }

    LNode* p = getElem(L, index - 1);  //找到待插入位置的前一个结点
    newNode->next = p->next;
    p->next = newNode;

    return L;
}

单链表的删除操作

LinkList ListDelete(LinkList L, int index){  //删除
    //方法一:通过获取index前面一个元素的结点,指向index后面一个元素的结点
    //方法二:
    LNode* front = L->next; //当前结点的前一个
    LNode* cur = NULL;      //当前结点

    if (index == 1){  //删除第一个结点
        L->next = front->next;
        free(front);
        return L;
    }

    while (index > 2){  //遍历寻找当前结点的前一个结点
        front = front->next;
        index--;
    }
    cur = front->next;
    front->next = cur->next;
    free(cur);  //释放被删除结点的空间
    return L;
}

单链表的销毁操作

LinkList ListDestory(LinkList L){
    L->next = NULL;  //将头节点的next置空
    free(L);  //释放头节点的空间
    return L;
}

单链表的输出操作

void printList(LinkList L){  //输出
    LNode* p = L->next;
    while (p != NULL){
        printf("%d ", p->data);
        p = p->next;
    }
    printf("\n");
}

单链表的取值操作

在单链表中从第一个结点出发,顺指针的next域逐个往下搜索,直到找到第index个结点位置,否在返回最后一个指针的域NULL。
LNode* getElem(LinkList L, int index){//取值
    LNode* p = L->next;
    int i = 1;
    if (index == 0) {  //返回头节点
        return L;
    }
    if (index < 0){  //index不合法
        return NULL;
    }
    while (i < index && p){  //i小于index,且p不为空
        p = p->next;
        i++;
    }
    
    return p;
}

源码

Linklist.h
#include <stdio.h>
#include <windows.h>
#include <malloc.h>

typedef int ElemType;
typedef struct LNode{
    ElemType data;
    struct LNode* next; 
}LNode, *LinkList;


void menu(); //菜单
LinkList InitList(); //初始化
void printList(LinkList L); //输出
LNode* getElem(LinkList L, int index); //取值
LNode* LocatElem(LinkList L, ElemType elem); //查找
LinkList ListInsert(LinkList L, int index, ElemType elem); //插入
LinkList ListDelete(LinkList L, int index); //删除
LinkList ListDestory(LinkList L); //销毁
LinkList List_Tail_Insert(LinkList L); //尾插
LinkList List_Front_Insert(LinkList L);//头插

Linklist.c
#include "Linklist.h"


void menu(){
    printf("< G取值  P打印  L查找  I插入  D删除  X销毁  Q退出 >\n");
    printf("请选择您的操作:");
}

LinkList InitList(){ //初始化
    LinkList L = (LinkList)malloc(sizeof(LNode)); //C开辟动态内存
    //L = new (LNode);  //C++开辟动态内存
    if (L == NULL){
        return NULL;    //内存不足,分配失败
    }
    L->next = NULL; //将L的指针域设为空
    return L;
}

LNode* getElem(LinkList L, int index){//取值
    LNode* p = L->next;
    int i = 1;
    if (index == 0) {  //返回头节点
        return L;
    }
    if (index < 0){  //index不合法
        return NULL;
    }
    while (i < index && p){  //i小于index,且p不为空
        p = p->next;
        i++;
    }
    
    return p;
}

void printList(LinkList L){  //输出
    LNode* p = L->next;
    while (p != NULL){
        printf("%d ", p->data);
        p = p->next;
    }
    printf("\n");
}

LNode* LocatElem(LinkList L, ElemType elem){ //查找
    LNode* p = L->next;
    while (p != NULL && p->data != elem){
        p = p->next;
    }
    return p;  //返回该结点
}
LinkList ListInsert(LinkList L, int index, ElemType elem){ //插入
    LNode* newNode = (LNode*)malloc(sizeof(LNode));
    newNode->data = elem;  //待插入的结点

    if (index == 1){  //类似头插
        newNode->next = L->next;
        L->next = newNode;
        return L;
    }

    LNode* p = getElem(L, index - 1);  //找到待插入位置的前一个结点
    newNode->next = p->next;
    p->next = newNode;

    return L;
}

LinkList ListDelete(LinkList L, int index){  //删除
    //方法一:通过获取index前面一个元素的结点,指向index后面一个元素的结点
    //方法二:
    LNode* front = L->next; //当前结点的前一个
    LNode* cur = NULL;      //当前结点

    if (index == 1){
        L->next = front->next;
        free(front);
        return L;
    }

    while (index > 2){  //遍历寻找当前结点的前一个结点
        front = front->next;
        index--;
    }
    cur = front->next;
    front->next = cur->next;
    free(cur);
    return L;
}

LinkList ListDestory(LinkList L){
    L->next = NULL;
    free(L);
    return L;
}

LinkList List_Front_Insert(LinkList L){ //初始化头插
    printf("请输入数据(-1结束):");
    int n;
    LNode* newNode;  //新节点

    scanf("%d", &n);
    while (n != -1){
        newNode = (LNode*)malloc(sizeof(LNode));
        newNode->data = n;
        newNode->next = L->next;
        L->next = newNode;

        scanf("%d", &n);
    }
    return L;
}

LinkList List_Tail_Insert(LinkList L){ //初始化尾插
    printf("请输入数据(-1结束):");
    int n;
    LNode* newNode;  //新节点
    LNode* tail = L; //尾结点

    scanf("%d", &n);
    while ( n!=-1 ){
        newNode = (LNode*)malloc(sizeof(LNode));
        newNode->data = n;
        tail->next = newNode;
        tail = newNode;
        
        scanf("%d", &n);
    }
    tail->next = NULL;
    return L;
}

test.c
#include "Linklist.h"

int main(){
    LinkList L = InitList(); // 初始化
    L = List_Tail_Insert(L); //数据尾插
    //L = List_Front_Insert(L); //数据头插
    
    while (1){
        menu();
        char key;
        int n = 0;
        int index = 0;
        LNode* p = NULL;
        getchar();  //释放scanf读取的\n
        scanf("%c", &key);

        switch(key){
            case 'G':
                printf("要查找第几个元素:");
                scanf("%d", &n);
                p = getElem(L, n);
                if (p != NULL){
                    printf("%d\n", p->data);
                }
                else{
                    printf("输入有误!\n");
                }
                break;

            case 'P':
                printList(L);
                break;

            case 'L':
                printf("要查找的元素:");
                scanf("%d", &n);
                p = LocatElem(L, n);
                if (p != NULL){
                    printf("找到了该元素:%d\n", p->data);
                }
                else{
                    printf("没有该元素\n");
                }
                break;

            case 'I':
                printf("请输入插入的下标和数:");
                scanf("%d %d", &index, &n);
                L = ListInsert(L, index, n);
                printf("插入成功!\n");
                break;

            case 'D':
                printf("要删除第几个元素:");
                scanf("%d", &n);
                p = ListDelete(L, n);
                if (p != NULL){
                    printf("删除成功!\n");
                }
                else{
                    printf("删除失败!\n");
                }
                break;

            case 'X':
                L = ListDestory(L);
                if (L == NULL){
                    printf("链表已经销毁!\n");
                }
                else{
                    printf("链表销毁失败!\n");
                }
                break;

            case 'Q':
                printf("退出成功!");
                exit(0);
        }
    }
    system("pause");
}

猜你喜欢

转载自blog.csdn.net/qq_56627079/article/details/129542090