线性表的链式表示和实现

来源:互联网 发布:免费淘宝账号和密码 编辑:程序博客网 时间:2024/05/18 13:05

线性表的链式表示和实现

首先来看一下线性表的顺序存储和链式存储的区别
顺序存储结构 —— 可随机存储,但插入或删除需要移动大量元素
链式存储结构 —— 便于插入或删除,但不可随机存取(其实可以通过操作使其随机存取)

线性链表

以存储的数据为整型(int)为例:

头结点的定义:

typedef struct HNode{    int length;    char info[100];    struct LNode *next;}HNode;

注:大部分示例程序都直接用链表节点的类型来声明头节点,但我觉得应该为头节点定义单独的类型,也许这样会使操作变得略微麻烦,但也会带来很多好处。比如,当链表中的节点存储的数据为浮点型数组、字符型数组等类型的数据,而头结点是用整形来存储链表的长度的时候,分开定义更为合理。

链表节点的定义

typedef struct LNode{    int data;    struct LNode *next;}LNode;

1、创建空链表

HNode* createNullList()         /**创建空链表的函数的定义**/{    HNode* head;    head=(HNode*)malloc(sizeof(HNode));    head->length = 0;    if(head!=NULL){        head->next=NULL;        printf("Has create null list success!\n");    }    else        printf("Out of space!\n");    return head;}

2、判断链表是否为空

int isNullList(HNode *head)      /**判断是否链表是否为空的函数的定义(Y-1,N-0)**/{    return head->next==NULL;}

3、在链表的结尾添加新节点

int append_t(HNode *head, int n)      /**在已存在的链表最后增加一个新结点的函数的定义(Y-1,N-0)**/{    LNode *p, *pnew;    pnew=(LNode*)malloc(sizeof(LNode));    if(pnew==NULL){        printf("Out of space!\n");        return 0;    }    else{        pnew->data = n;        p = head->next;                 /*p先指向头结点*/        if(p == NULL){                  /*如果链表为空*/            head->next = pnew;            pnew->next = NULL;        }        else{            while(p->next!=NULL)        /*若p所指不是链尾*/                p=p->next;              /*p后移一个结点*/            p->next=pnew;               /*链尾的next存储新结点指针*/            pnew->next=NULL;            /*使新结点成为链尾*/        }        head->length++;    }    return 1;}

4、由结点中的元素查找结点的位序

int locate(HNode *head, int n, LNode **p)  /**求某结点的指针,并返回其位序的函数的定义**/{    int i = 1;    *p = NULL;    *p = head->next;                   /*将头结点的next域赋值给p,使指向第一个结点*/    while(*p != NULL && (*p)->data != n){        i++;        *p = (*p)->next;    }    if(*p == NULL)        return 0;    return i;}

5、由某结点的指针查找该节点的前驱结点的指针

LNode* locatePre(HNode *head, LNode *p)   /**求p所指结点的前驱的函数的调用**/{    LNode *ptemp;    ptemp = head->next;    while(ptemp != NULL && ptemp->next != p)        ptemp = ptemp->next;    return ptemp;}

6、在某结点之后插入一个新结点

int append_t(HNode *head, int n)      /**在已存在的链表最后增加一个新结点的函数的定义(Y-1,N-0)**/{    LNode *p, *pnew;    pnew=(LNode*)malloc(sizeof(LNode));    if(pnew==NULL){        printf("Out of space!\n");        return 0;    }    else{        pnew->data = n;        p = head->next;                 /*p先指向头结点*/        if(p == NULL){                  /*如果链表为空*/            head->next = pnew;            pnew->next = NULL;        }        else{            while(p->next!=NULL)        /*若p所指不是链尾*/                p=p->next;              /*p后移一个结点*/            p->next=pnew;               /*链尾的next存储新结点指针*/            pnew->next=NULL;            /*使新结点成为链尾*/        }        head->length++;    }    return 1;}

7、删除结点

int deletendnd(HNode *head, int i, int *e)           /**结点的删除函数的定义**/{    int j = 0;    LNode *p, *q;    p = head->next;    if(i == 1){        j = 1;        head->next = p->next;        *e = p->data;        free(p);        return 1;    }    while(p->next != NULL && j < i-2){        p = p->next;        j++;    }    if(!(p->next) || j > i-2)        return 0;    q = p->next;    p->next = q->next;    *e = q->data;    free(q);    head->length--;    return 1;}

————————————————————————————-

完整代码:

除了以上基本操作外,本代码又添加了一些其他功能,并且改善了交互性。
本代码的头结点与其余结点采用的是不同的数据类型,因此增加了代码的复杂性

#include <stdio.h>#include <stdlib.h>#include <string.h>typedef struct LNode{    int data;    struct LNode *next;}LNode;typedef struct HNode{    int length;    char info[100];    struct LNode *next;}HNode;HNode* createNullList();                /**创建空链表的函数的声明**/int isNullList(HNode*);                 /**判断是否链表是否为空的函数的声明(Y-1,N-0)**/int append_h(HNode*, int);                /**在已存在的链表最前增加一个新结点的函数的声明(Y-1,N-0)**/int append_t(HNode*, int);                /**在已存在的链表最后增加一个新结点的函数的声明(Y-1,N-0)**/int locate(HNode*, int, LNode**);              /**求某结点的指针并返回位序的函数的声明**/LNode* locatePre(HNode*, LNode*);        /**求p所指结点的前驱的函数的声明**/LNode* locfda(HNode*, int);             /**查找某位序的元素的数据的函数的声明**/int insert(HNode*, LNode*, int);      /**在某结点之后插入一个新结点的函数的声明(Y-1,N-0)**/int deletendndnd(HNode*, int);                 /**结点的删除函数的声明**/int clear(HNode*);                      /**清空链表的函数的声明**/int batchadd(HNode*, int, int*);                   /**批量添加结点的函数的声明**/void reverse(HNode*);                   /**单链表的就地逆置函数的声明**/void print_L(HNode*);void print_hyphen(int);/******************************************************************************************************************/int main(void){    int data;             /*结构体成员的数据*/    LNode *p;    print_hyphen(5);    printf("单链表的操作示例");    print_hyphen(5);    printf("\n");    HNode *head;    if((head=createNullList()) != NULL)      /**创建空链表的函数的调用**/    {        char info[50];        printf("请输入此链表的信息(50个字符以内):\n");        gets(info);        strcpy(head->info, "The example for CSDN!\n");        strcpy(head->info + strlen("The example for CSDN!\n"), info);    }    else{        exit(1);    }    int end = 0;    while(!end){        print_hyphen(15); printf("\n");        printf("请输入指令来执行操作\n");        print_hyphen(15); printf("\n");        printf("1、判断链表是否为空\n2、在链表最前增加一个新结点\n3、在链表最后增加一个新结点\n4、查找某位序的元素的数据\n");        printf("5、在某结点之后插入一个新结点\n6、删除某结点并返回其值\n7、查找某元素的位序\n8、清空链表\n");        printf("9、求某结点的前驱\n10、查看链表信息\n11、批量添加结点\n12、显示链表长度\n13、查看链表数据\n14、逆置链表\n15、退出演示\n");        print_hyphen(15); printf("\n");        printf("输入要使用的功能的序号: ");        int opt;        scanf("%d",&opt);        print_hyphen(15);        printf("\n");        switch(opt){            case 1:                if(isNullList(head))       /**判断是否链表是否为空的函数的调用(Y-1,N-0)**/                    printf("链表为空!\n");                else                    printf("链表不为空!\n");                break;            case 2:                printf("请输入要添加到链头的结点的数据: ");                scanf("%d",&data);                   /**输入要添加的结点的数据*/                if(append_h(head, data))           /**在已存在的链表最后增加一个新结点的函数的调用(Y-1,N-0)**/                    printf("添加成功!\n");                print_L(head);                break;            case 3:                printf("请输入要添加到链尾的结点的数据: ");                scanf("%d",&data);                   /**输入要添加的结点的数据*/                if(append_t(head, data))           /**在已存在的链表最后增加一个新结点的函数的调用(Y-1,N-0)**/                    printf("添加成功!\n");                print_L(head);                break;            case 4:{                int site;                printf("请输入位序号: ");                scanf("%d",&site);                p = locfda(head, site);                if(p != NULL)                    printf("Has find the node!\n其数据为:%d\n", p->data);                else                    printf("Don't find the node!\n");                break;            }            case 5:                printf("请输入要求在其后插入新结点的结点的数据: ");                scanf("%d",&data);                locate(head, data, &p);                int isinsert;                printf("请输入新结点的数据: ");                scanf("%d",&data);                isinsert = insert(head, p, data);  /**在某结点之后插入一个新结点的函数的调用(Y-1,N-0)**/                if(isinsert)                    printf("插入成功!\n");                else                    printf("未插入成功!\n");                print_L(head);                break;            case 6:                printf("请输入要删除的结点的位序: ");                int deletesi;                scanf("%d",&deletesi);                int deletend;                if(deletendnd(head,deletesi,&deletend))             /**结点的删除函数的调用**/                    printf("删除成功!\n其值为: %d\n", deletend);                else                    printf("未删除成功!\n");                print_L(head);                break;            case 7:                printf("请输入要寻找的结点的数据: ");                int islocate;                scanf("%d",&data);                LNode *head_findnode;       /*要寻找的结构体的指针*/                islocate = locate(head, data, &head_findnode);   /**求某结点的指针的函数的调用**/                if(head_findnode != NULL)                    printf("Has find the node!\n其位序为:%d\n", islocate);                else                    printf("Don't find the node!\n");                break;            case 8:                if(clear(head))                    printf("清空成功!\n");                else                    printf("清空失败!\n");                break;            case 9:                printf("请输入要求前驱结点的结点的数据: ");                scanf("%d",&data);                LNode *prep;                locate(head, data, &p);                prep=locatePre(head,p);        /**求p所指结点的前驱的函数的调用**/                if(prep==NULL)                    printf("Don't find the prenode!\n");                else                    printf("Has find the prenode!The data is %d\n",prep->data);                break;            case 10:                printf("%s\n", head->info);                break;            case 11:{                int i;                int batchnum;                int batch[100];                printf("请输入要批量添加的结点的个数: ");                scanf("%d",&batchnum);                printf("请输入各结点的数据(用空格隔开): ");                for(i = 0; i < batchnum; i++)                    scanf("%d", batch+i);                if(batchadd(head, batchnum, batch))                    printf("批量添加成功!\n");                print_L(head);                break;            }            case 12:                printf("当前链表长度为: %d\n", head->length);                break;            case 13:                print_L(head);                break;            case 14:                reverse(head);                printf("链表逆置后为:\n");                print_L(head);                break;            case 15:                print_hyphen(15);                printf("\n");                printf("再见!\n");                print_hyphen(15);                end = 1;                break;            default:                print_hyphen(15);printf("\n");                printf("无此序号,请重新输入!\n");                print_hyphen(15);printf("\n");        }    }    return 0;}/*********************************************************************************************************************/HNode* createNullList()         /**创建空链表的函数的定义**/{    HNode* head;    head=(HNode*)malloc(sizeof(HNode));    head->length = 0;    if(head!=NULL){        head->next=NULL;        printf("Has create null list success!\n");    }    else        printf("Out of space!\n");    return head;}int isNullList(HNode *head)      /**判断是否链表是否为空的函数的定义(Y-1,N-0)**/{    return head->next==NULL;}int append_h(HNode *head, int n)               /**在已存在的链表最前增加一个新结点的函数的定义(Y-1,N-0)**/{    LNode *p, *pnew;    pnew = (LNode*)malloc(sizeof(LNode));    if(pnew == NULL){        printf("Out of space!\n");        return 0;    }    pnew->data = n;    pnew->next = head->next;    head->next = pnew;    head->length++;    return 1;}int append_t(HNode *head, int n)      /**在已存在的链表最后增加一个新结点的函数的定义(Y-1,N-0)**/{    LNode *p, *pnew;    pnew=(LNode*)malloc(sizeof(LNode));    if(pnew==NULL){        printf("Out of space!\n");        return 0;    }    else{        pnew->data = n;        p = head->next;                 /*p先指向头结点*/        if(p == NULL){                  /*如果链表为空*/            head->next = pnew;            pnew->next = NULL;        }        else{            while(p->next!=NULL)        /*若p所指不是链尾*/                p=p->next;              /*p后移一个结点*/            p->next=pnew;               /*链尾的next存储新结点指针*/            pnew->next=NULL;            /*使新结点成为链尾*/        }        head->length++;    }    return 1;}int locate(HNode *head, int n, LNode **p)  /**求某结点的指针,并返回其位序的函数的定义**/{    int i = 1;    *p = NULL;    *p = head->next;                   /*将头结点的next域赋值给p,使指向第一个结点*/    while(*p != NULL && (*p)->data != n){        i++;        *p = (*p)->next;    }    if(*p == NULL)        return 0;    return i;}LNode* locatePre(HNode *head, LNode *p)   /**求p所指结点的前驱的函数的调用**/{    LNode *ptemp;    ptemp = head->next;    while(ptemp != NULL && ptemp->next != p)        ptemp = ptemp->next;    return ptemp;}LNode* locfda(HNode *head, int n)              /**查找某位序的元素的数据的函数的定义**/{    LNode *p = head->next;    if(n < 1 || n > head->length)        return NULL;    while(n > 1 && p != NULL){        p = p->next;        n--;    }    if(n > 1)        return NULL;    else        return p;}int insert(HNode *head, LNode *p, int n)  /**在某结点之后插入一个新结点的函数的定义(Y-1,N-0)**/{    LNode *pnew = (LNode*)malloc(sizeof(LNode));    if(pnew == NULL){        printf("Out of space!\n");        return 0;    }    pnew->data = n;    pnew->next = p->next;    p->next = pnew;    head->length++;    return 1;}int batchadd(HNode *head, int n, int *s)                /**批量添加结点的函数的定义**/{    LNode *p, *pnew;    int i;    p = head->next;    if(head->next == NULL){        pnew=(LNode*)malloc(sizeof(LNode));        if(pnew==NULL){            printf("Out of space!\n");            return 0;        }        pnew->data = s[0];        head->next = pnew;        pnew->next = NULL;        p = pnew;        head->length++;        i = 1;    }    else{        while(p->next != NULL)            p = p->next;        i = 0;    }    while(i < n){        pnew=(LNode*)malloc(sizeof(LNode));        if(pnew==NULL){            printf("Out of space!\n");            return 0;        }        pnew->data = s[i];        pnew->next = NULL;        p->next = pnew;        p = pnew;        i++;        head->length++;    }    return 1;}int deletendnd(HNode *head, int i, int *e)           /**结点的删除函数的定义**/{    int j = 0;    LNode *p, *q;    p = head->next;    if(i == 1){        j = 1;        head->next = p->next;        *e = p->data;        free(p);        return 1;    }    while(p->next != NULL && j < i-2){        p = p->next;        j++;    }    if(!(p->next) || j > i-2)        return 0;    q = p->next;    p->next = q->next;    *e = q->data;    free(q);    head->length--;    return 1;}int clear(HNode *head){    LNode *pa, *pb;    pa = pb = head->next;    while(pa != NULL && pb != NULL){        pb = pa->next;        free(pa);        pa = pb->next;        free(pb);    }    return 1;}void reverse(HNode *head)                   /**单链表的就地逆置函数的定义**/{    LNode *p, *q;    p = head->next;    head->next = NULL;    while(p != NULL){        q = p;        p = p->next;        q->next = head->next;        head->next = q;    }}void print_L(HNode *head){    printf("\n当前链表中的数据为:\n");    LNode *p = head->next;    while(p != NULL){        printf("%d ", p->data);        p = p->next;    }    printf("\n");}void print_hyphen(int n){    while(n--)        printf("-");}
原创粉丝点击