700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > c语言 链表_小陈的C语言笔记---链表(详细讲解基本操作和概念)

c语言 链表_小陈的C语言笔记---链表(详细讲解基本操作和概念)

时间:2020-01-30 14:01:22

相关推荐

c语言 链表_小陈的C语言笔记---链表(详细讲解基本操作和概念)

关于链表的TIPS:

链表中各结点在内存中可以不是连续存放的,各数据接点的存储顺序与数据元素之间的逻辑关系可以不一致,而数据元素之间的逻辑关系是由指针域来确定的。在链表结点 的数据结构中,结构体内的指针域的数据类型可以使用未定义成功的数据类型,这是C语言中唯一规定可以先使用后定义的数据结构头指针:存放一个地址(头结点地址),指向第一个结点(一定不要把头结点当做头指针,头指针只不过是储存头结点的地址而已,我在学的时候这里总出错)具体链表的结构体建立,包括链表的指针域和数据域如下:

struct student

{

int num;

float score;

student *next;

};

建立单链表的一些约定每个结点类型用LinkList表示数据域 data(类型:通用类型标识符 ElemType)指针域 next

typedef struct LNode

{

ElemType data;

struct LNode *next;

}LinkList;

关于链表头结点的问题,有头结点只是为了方便计算(删除、插入……),因为只要掌握了表头,就可以访问整个链表

创建单链表

头插法新产生的结点作为新的表头插入链表
(第一次执行②的作用是确定尾指针NULL)

#include<stdio.h>LinkList*CreateListF(ElemType a[],int n){LinkList*head,*s;int i;head = (LinkList*)malloc(sizeof(LinkList)); //创建头结点head->next = NULL;for(i=0;i<n;i++){s = (LinkList*)malloc(sizeof(LinkList)); //创建新结点s->data=a[i];s->next=head->next; //第一次执行时是为了确定尾指针NULLhead->next=s; //将*s插在原开始结点之前、头结点之后}return head;}

尾插法(一句话,相当于不断开创新的结点,然后不断将新的结点的地址当做尾结点。尾结点不断后移,而新创的结点时按照创建的先后顺序而连接的。先来新到)新的结点插入到当前链表的表尾,使其成为当前链表的尾结点尾插法创建第一个结点刚开始为头结点开辟内存空间,因为此时除头结点没有新的结点的建立,接着将头结点的指针域 head->next 的地址赋为 NULL。此时,整个链表只有一个头结点有效,因此这时head既是头结点,又是尾结点。将头结点的地址赋给尾结点end后:end = head。 (此时end 就是 head, head 就是 end。 end->next 也自然指向的是 NULL。)尾插法创建第二个结点创建完第一个结点之后,我们开始创建第二个结点。第一个结点,end 和 head 共用一块内存空间。现在从堆中心开辟出一块内存给 node,将 node 的数据域赋值后,此时 end 中存储的地址是 head 的地址。此时,end->next 代表的是头结点的指针域,因此 end->next = node 代表的就是将上一个,也就是新开辟的 node 的地址赋给 head 的下一个结点地址。此时,end->next 的地址是新创建的 node 的地址,而此时 end 的地址还是 head 的地址。 因此 end = node ,这条作用就是将新建的结点 node 的地址赋给尾结点 end。 此时 end 的地址不再是头结点,而是新建的结点 node。尾插法创建单链表,结点创建完毕最后,当结点创建完毕,最后不会有新的结点来替换end,因此最后需要加上一条end->next = NULL。将尾指针的指向为NULL。

Linklist Creat_list(Linklist head) {head = (Linklist)malloc(sizeof(Lnode));// 为头指针开辟内存空间Linklist node = NULL; // 定义结点Linklist end = NULL; // 定义尾结点head->next = NULL; // 初始化头结点指向的下一个地址为 NULLend = head; // 未创建其余结点之前,只有一个头结点int count = 0 ; // 结点个数printf("Input node number: ");scanf("%d", &count);for (int i = 0; i < count; i++) {node = (Linklist)malloc(sizeof(Lnode));// 为新结点开辟新内存node->data = i; // 新结点的数据域赋值end->next = node;end = node;}end->next = NULL;}//完整的代码实践#include<stdio.h>#include<stdlib.h>struct node{int num,score;struct node*next;};int main(){struct node*creat(int n);void print(struct node*);struct node*head=0;head=creat(5);print(head);return 0;}struct node*creat(int n){struct node*h=0,*p,*q;int i;h=(struct node*)malloc(sizeof(struct node));p=h;h->next=0;scanf("%d%d",&h->num,&h->score); //初始化头指针for(i=1;i<n;i++){q=(struct node*)malloc(sizeof(struct node));scanf("%d%d",&q->num,&q->score);if(h==0)h=q; //如果malloc函数申请空间失败,则q变成头结点elsep->next=q;p=q;}p->next=0;return h;}void print(struct node*h) //输出不带头结点的链表{while(h){printf("num=%dtscore=%dn",h->num,h->score);h=h->next;}}

单链表的基本运算

初始化链表InitList

LinkList*InitList(){LinkList*head;head=(LinkList*)malloc(sizeof(LinkList));head->next=NULL;return head;}

销毁链表逐一释放全部结点空间

void DestroyList(LinkList*head){LinkList*p=head,*q;while(p!=NULL){q=p;p=p->next;free(q);}}

求链表长度

int ListLength(LinkList*head){LinkList*p=head;int i=0;while(p!=NULL){i++;p=p->next;}return(i);}

判定链表是不是空表

int ListEmpty(LinkList*head){return(head->next==NULL);}

输出链表

void DispList(LinkList*head){LinkList*p=head;while(p!=NULL){printf("%c",p->data);p=p->next;}printf("n");}

求指定位置的某个数据元素(在链表中从头开始找到第i个数据结点,若存在,则将其data域值通过变量e带回)

int GetELem(LinkList*head,int i,Elem Type*e){int j=1;LinkList*p=head->next;while(p!=NULL&&j<i){j++;p=p->next;}if(p==NULL)return 0;else{*e=p->data;return 1; //表示代码执行成功}}

按元素值定位查找(在链表中从头开始找第一个值域与e相等的结点,若存在,则返回其次序,否则返回0)

int LocateElem(LinkList*head,Elem Type e){int n=1;LinkList*p=head->next;while(p!=NULL&&p->data!=e){n++;p=p->next;}if(p=NULL)return 0;elsereturn n;}

插入数据元素(先在链表中找到第i个结点*p,若存在,将值为e分结点*s插入其后)

int ListInsert(LinkList*head,int i,ElemType e){int j=0;LinkList*p=head,*s;while(p!=NULL&&j<i-1){j++;p=p->next;}if(p==NULL)return 0;else{s=(LinkList*)malloc(sizeof(LinkList));s->data=e;s->next=p->next;p->next=s;return 1;}}

删除数据元素

int ListDelete(LinkList*head,int i,ElemType e){int j=0;LinkList*p=head,*q;while(p!=NULL&&j<i-1){j++;p=p->next;}if(p==NULL)return 0;else{q=p->next;if(q==NULL)return 0;p->next=q->next;free(q);return 1;}}

链表的逆置

算法图解

void RevLink(LinkList L){Node *p=L->next,*q; //创建指针p使其指向第二个结点(L是第一个结点的地址,L->next是第二个结点的地址)L->next=NULL; //这里是说把第一个结点的指针域置0,这样就为第一个结点作尾结点做准备(因为逆置后原来的第一个结点就变成了尾结点呀)while(q){q=p->next; //只要第一个结点之后一直有结点,q指针就一直向下走,直到q为空p->next=L->next; //插入操作,将逆置的结点往头结点之前插L->next=p;//将链表连接起来p=q;}}

单链表的连接(数据域排序)

LinkList MergeLinkList(LinkList LA,LinkList LB){Node *pa,*pb;LinkList LC;pa=LA->next;pb=LB->next;LC=LA;//建立两个链表连接之后的新链表的头指针 LC->next=NULL;r=LC;//r是一个搜索指针,从头开始,最后成为尾指针 while(pa&&pb){if(pa->data<=pb->data){r->next=pa;r=pa;pa=pa->next;}else{r->next=pb;r=pb;pb=pb->next;}}if(pa)//根据pa是否为空,判断最后的尾指针是谁 r->next=pa;elser->next=pb;free(LB);//释放多余的空间 return(LC);}

本人也是第一次写知乎文章,希望对童鞋们有帮助呀,我也是一个大学生,还在学习中,这是我每天学习自己进行的总结和知识理解梳理,如果有错误的话希望大佬多多指教,后续我会继续更新C语言的知识梳理类文章,如果觉得文章对你有帮助的话,别忘了点下赞或者评下论再走哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。