首页 > 技术文章 > C语言----------链表的简单实现与操作

AraragiTsukihi 2017-01-06 17:49 原文

链表是一种物理存储单元上非连续、非顺序的存储结构数据元素的逻辑顺序是通过链表中的指针链接次序实现的。

 

链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。

 

每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,操作复杂。

 

由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度(注意这里指的是链表在插入后,无需改变其他元素的内存地址),比另一种线性表(这里指的是数组在某个位置插入后需要将该位置之后的元素都后移一位,因此复杂度为O(n))快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而有序的顺序表相应的时间复杂度分别是O(logn)O(1)(前者指的是使用折半查找等方法,后者指的是直接用下标访问数组元素)

 

链表的简单实现及操作:

 

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

typedef struct node{ //定义节点类型
    char data; //数据域
    struct node *next; //指针域
}linklist;
linklist* Create(){ //创建链表
    char key;
    linklist *phead; //头指针
    linklist *pnew; //新节点
    linklist *pend; //尾指针
    phead = (linklist*)malloc(sizeof(linklist));
    pend = phead;
    puts("请输入你要创建的链表,以$结束");
    key=getchar();
    while(key!='$'){
        pnew = (linklist*)malloc(sizeof(linklist));
        pnew ->data = key;
        pend ->next = pnew; //新节点插入表尾
        pend=pnew; //尾指针指向新表尾
        key=getchar();
    }
    pend->next = NULL; //将尾节点指向的下一节点设置为空
    return phead; //返回头指针
}
void Print(linklist *phead){ //打印链表
    linklist *p = phead->next;
    while(p!=NULL){
        printf("%c",p->data);
        p=p->next;
    }
    puts("");
}
linklist* Get(linklist* phead,int pos){ //查找第pos个的节点
    int cur = 0; //扫描器
    linklist *p;
    p = phead; //指向头节点
    while((p->next!=NULL)&&(cur<pos)){ //不合法或到达尾部则退出
        p = p->next;
        cur++;
    }
    return cur==pos?p:NULL;
}
int Locate(linklist* phead,char val){//查找值为val的节点位置
    int cur = 0,ok = 0;
    linklist *pnew = phead;
    while(pnew->next!=NULL){
        if(pnew->data==val){
            ok=1;
            break;
        }
        pnew=pnew->next;
        cur++;
    }
    return ok==1?cur:-1;
}
linklist *FindLocate(linklist *phead,int pos){ //查找倒数第K个节点的值 
    if(pos<=0) return NULL; //输入不合法则返回 
    linklist *pnew = phead;
    pos--;
    while(pos--){
        pnew = pnew -> next;
    }
    linklist *pnxt = phead;
    while(pnew->next!=NULL){
        pnew = pnew -> next;
        pnxt = pnxt -> next;
    }
    return pnxt;
}
void DeleteAfter(linklist *p){ //删除p的后继节点
    linklist *r;
    r = p->next;
    p->next = r->next;
    free(r);
}
void InsertAfter(linklist *p,char val){//插入p的后继节点
    linklist *pnew = (linklist*)malloc(sizeof(linklist));
    if(p->next!=NULL){
        pnew->next = p->next;
    }else{
        pnew->next = NULL;
    }
    pnew ->data = val;
    p->next = pnew;
}
void Insert(linklist* phead,int pos,char val){//插入val到位置为pos的节点之后
    int cur=0;
    linklist* p = Get(phead,pos-1);
    if(p!=NULL){
        InsertAfter(p,val);
        printf("插入成功!\n当前链表为");
        Print(phead);
    }else{
        puts("插入错误!");
    }
}
void Delete(linklist* phead,int pos){ //删除位置为pos的节点
    int cur=0;
    linklist* p =Get(phead,pos-1);
    if(p!=NULL&&(p->next)!=NULL){
        DeleteAfter(p);
        printf("删除成功!\n当前链表为");
        Print(phead);
    }else{
        puts("删除错误!");
    }
}
void Free(linklist*p){ //释放链表
    if(p->next!=NULL){
        Free(p->next);
    }
        free(p);
}
int main(void){
    linklist* phead =  Create(); //头指针
    Print(phead);
    int pos;
    char val;
    puts("请输入你要查找的位置");
    scanf("%d",&pos);
    linklist* pfind = Get(phead,pos);
    if(pfind !=NULL){
        printf("该位置值为%c\n",pfind->data);
    }
    else{
        puts("输入错误!");
    }
    puts("请输入你要查找的值");
    scanf(" %c",&val);
    int locate = Locate(phead,val);
    if(locate==-1){
        puts("输入错误!");
    }else{
        printf("该值位置为%d\n",locate);
    }
    puts("请输入你要查找的倒数第K个值");
       scanf("%d",&pos);
       pfind = FindLocate(phead,pos);
    if(pfind !=NULL){
        printf("倒数第K个数值为%c\n",pfind->data);
    }
    else{
        puts("输入错误!");
    }
    puts("请输入你要删除的位置");
    scanf("%d",&pos);
    Delete(phead,pos);
    puts("请输入你要插入的位置以及值");
    scanf("%d %c",&pos,&val);
    Insert(phead,pos,val);
    Free(phead);
    return 0;
}

 

推荐阅读