博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C语言实现双链表的(终端)添加和查询
阅读量:5780 次
发布时间:2019-06-18

本文共 5304 字,大约阅读时间需要 17 分钟。

文章如果有写的不对的地方,欢迎指正^^

双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。

通过双链表可以快速的了解c语言中的指针和内存的关系

细节

  • 指针变量存储的是内存的地址,可以理解为一个存储内存地址的符号

  • 声明的是类型,定义的是变量。声明的时候不分配内存,int i;属于定义。

  • 结构体声明时不分配内存,定义变量的时候才分配struct linked_list link_1;

  • 指针变量相互赋值,传递的是所代表的内存地址

  • 函数接受字符串的时候,形参要用char *来代表字符串数组的首地址

  • -> 用来表示调用结构体指针所代表的变量的域,如果用.则代表结构体变量调用自己的域

  • 判断一个指针是否为空,用== NULL

链表实现方案

/*describe linked_list _| |__ _ _ __ _| '_ \| | | |/ _` || |_) | |_| | (_| ||_.__/ \__,_|\__, |             |___/*/#include 
#include
struct linked_list { struct linked_list *next, *prev; char *title;};/* 声明结构体指针变量,会在内存中开辟空间,存储指针 */struct linked_list * current,* prev, *head;void list_add(char *);void list_search();void list_reverse_search();int main(void) { list_add("-"); list_add("--"); list_add("---"); list_add("----"); list_add("-----"); list_search(); list_reverse_search();}void list_add(char *title) { /* 将新申请的内存的首地址给结构体指针变量 */ current = (struct linked_list *)malloc(sizeof(struct linked_list)); /* 初始化当前结构体,新增元素的next始终是NULL */ current->next = NULL; current->title = title; /* prev元素是否已经存在了,是否存在前辈元素,来判断是否是首次添加元素*/ if(prev == NULL) { /* 如果不存在说明,current是第一个添加进来的元素 */ current->prev = NULL; /* 设置为首元素,这里current和head现在指向的是同一个内存地址 */ head = current; }else { /* 如果存在前辈元素,将当前元素的prev设置为前辈元素的地址,并且将前辈元素的next设置为当前元素的地址 */ current->prev = prev; prev->next = current; } /* 将当前指针所代表元素的地址,交给prev指针符号 ,现在head和prev指向同一个地址*/ prev = current; /* 首次添加元素head是没有next的,第二次添加的时候,prev 的next设置为了新增元素地址,所以head的next也发生了改变 ( 添加第2个元素的时候,才会重写上个元素的next值)*/}/* 链表正序搜索 */void list_search() { while(head) { printf("%s\n", head->title); head = head->next; }}/* 倒序搜索 */void list_reverse_search() { while(current) { printf("%s\n", current->title); current = current->prev; }}

终端向链表添加元素

我们来强化一下,通过终端来不停地向链表中添加元素。并且每次回车之后,都打印出整个列表的元素。

要点

  • 声明定义字符串数组的时候,值不能用变量

  • 我们要求每次都要保存填写的元素值,所以每次都需要重新开辟一个内存空间,给新的struct,由于个struct中都保存的是title的指针,所以新增加的元素的title也需要重新开辟内存空间来存储。

  • 由于每次都需要进行打印链表,所以head要注意不能被覆写。所以重新定义一个struct linked_list变量来做一个中间变量。

#include 
#include
#include
struct linked_list { struct linked_list *next, *prev; char *title;};struct linked_list *head,*current,*above;struct linked_list head_cp;void list_add(char *);void list_search();int main(int argc, char *argv[]) { char title[10]; while(scanf("%s",title) > 0) { list_add(title); /* 每次添加到链表之后,都会进行打印整个链表 */ list_search(); } /* 这样初始化是错误的 error: array initializer must be an initializer list or string literal “数组的初始化,必须是一个列表或者是字面的字符串” char title[] = *(argv+1); */}void list_add(char *t) { /* 分配内存 */ current = (struct linked_list *)malloc(sizeof(struct linked_list)); /* title 是一个内存空间的首地址,这里重新分配内存的原因是,每次scanf都会重写t指针下的内容,导致整个链式里面所有的title都发生变化 */ char *title = (char *)malloc(sizeof(*t)); /* 将t指针指向的内容copy到title指针指向的内存中 */ strcpy(title,t); /* 初始化结构体域 */ current->prev = NULL; current->next = NULL; /* 指向新内存中的title */ current->title = title; if(above == NULL) { head = current; }else { current->prev = above; above->next = current; } above = current;}void list_search() { /* 这将head指向的内容赋值给新开辟的结构体变量,这里不是给的地址,给的是内容 */ head_cp = *head; while(head_cp.title) { printf(">>%s\n", head_cp.title); if(head_cp.next != NULL) { head_cp = *(head_cp.next); }else { return; } }}

操作结果

1  /* 回车 */>>12  /* 回车 */>>1>>23  /* 回车 */>>1>>2>>34  /* 回车 */>>1>>2>>3>>4

能不能不手动分配title的内存空间呢?

当然可以。下面代码中我们修改了struct的结构将原来的char *title修改为char title[10],这样每次定义结构体变量的时候,内存作为struct的一部分一起分配好了。

那么我们在add元素的时候,就需要将scanf获取到的变量,通过strcpy(current->title,title)的方式,写入到char title[10]开辟的内存空间中。

还需要修改list_search方法中的while判断,不能再判断指针是否为NULL的方式来判断是否存在title内容,而是要判断字符串的长度strlen(head_cp.title) == 0

但是最后一种修改结构体的方式无法动态分配内存,每次生成的字符串的长度都是10,会浪费内存。

#include 
#include
#include
struct linked_list { struct linked_list *next, *prev; char title[10];};struct linked_list *head,*current,*above;struct linked_list head_cp;void list_add(char *);void list_search();int main(int argc, char *argv[]) { char title[10]; while(scanf("%s",title) > 0) { list_add(title); /* 每次添加到链表之后,都会进行打印整个链表 */ list_search(); } /* 这样初始化是错误的 error: array initializer must be an initializer list or string literal “数组的初始化,必须是一个列表或者是字面的字符串” char title[] = *(argv+1); */}void list_add(char *title) { /* 分配内存 */ current = (struct linked_list *)malloc(sizeof(struct linked_list)); /* 初始化结构体域 */ current->prev = NULL; current->next = NULL; /* 这里current->title是字符串数组的首地址,是个指针 */ strcpy(current->title,title); if(above == NULL) { head = current; }else { current->prev = above; above->next = current; } above = current;}void list_search() { /* 这将head指向的内容赋值给新开辟的结构体变量,这里不是给的地址,给的是内容 */ head_cp = *head; while(strlen(head_cp.title) != 0) { printf(">>%s\n", head_cp.title); if(head_cp.next != NULL) { head_cp = *(head_cp.next); }else { return; } } }

转载地址:http://xouyx.baihongyu.com/

你可能感兴趣的文章
springcloud使用zookeeper作为config的配置中心
查看>>
校园火灾Focue-2---》洗手间的一套-》电梯
查看>>
css控制文字换行
查看>>
bzoj1913
查看>>
L104
查看>>
分镜头脚本
查看>>
链表基本操作的实现(转)
查看>>
邮件发送1
查看>>
[转] libcurl异步方式使用总结(附流程图)
查看>>
编译安装LNMP
查看>>
[转]基于display:table的CSS布局
查看>>
crm 02--->讲师页面及逻辑
查看>>
AS3.0 Bitmap类实现图片3D旋转效果
查看>>
Eigen ,MKL和 matlab 矩阵乘法速度比较
查看>>
带三角的面包屑导航栏(新增递增数字)
查看>>
Web应用程序安全与风险
查看>>
codeforces 984 A. Game
查看>>
CSS居中
查看>>
One Person Game(概率+数学)
查看>>
CodeForces 258B Little Elephant and Elections :于1-m中找出七个数,使六个数里面的4和7个数比第七个数严格小:数位dp+dfs...
查看>>