⑴ c语言里面的链表是什么
C语言里面的链表是一种数据结构
是一种线形的存储结构
链表和数组一样,也是将一组同类型的数据组织在一起的一种数据结构
不同的是
数组采用的是顺序存储,依靠数组的首地址和元素的相对地址(下标)来实现访问。
优点是访问方便快捷,而缺点是数组是静态的,不利于实现元素的动态增减。
而链表采用的是离散存储,依靠节点间的指向下一个节点的指针来实现访问。
其优缺点和数组相反
⑵ C语言中链表是怎样调用的
->运算是间接寻址,你用多指针的话会发现指针用->这种调用方式更简洁
链表指针是C语言的一个难点,但也是重点,学懂了非常有用。要仔细讲就必须先讲变量、指针。
什么是变量?所谓变量,不要浅显的认为会变得量就是变量。举个例子:“教室变不变?”变,因为每天有不同的人在里面上课,但又不变,因为教室始终在那,没有变大或变小。这就是变量:有一个不变的地址和一块可变的存储空间。正常情况下,我们只看到变量这个房间里面的东西,也就是其内容,但不会关注变量的地址,但是C语言的指针,就是这个房间的地址。我们声明变量就相当于盖了间房子存放东西,我们可以直接观看房子里的东西,而声明指针,就是相当于获得了一个定位器,当用指针指向某个变量时,就是用指针给变量定位,以后我们就可以用指针找到他所“跟踪”的变量并可以获得里面的内容。
至于我们写代码的结构体就相当于是有好几个房子组成的别墅,几个房子绑定在一起使用。假设现在有很多这种别墅分布在一个大迷宫里,每间别墅里都有一间房子。里面放了另一个别墅的位置信息,现在你手拿定位器找到了第一栋别墅,从里面得到了你想要的东西(链表的数据部分),然后把下一栋别墅的位置计入你的定位器(p
=
p->next),再走向下一栋别墅……如此走下去,知道走到某地下一栋别墅信息没有了(p->next
==
NULL),你的旅行结束。这就是链表一次遍历的过程。
aTdPage[ucTdPageIndex]->OnInit
();就相当于一个定位器
⑶ 用c语言创建链表
void CreateList_H(Linklist L,int n)中的L是局部变量,你生成的头结点L不能被返回,应该改为:
Linklist CreateList_H(int n)
调用方式和函数内部返回值都需要相应改动。
⑷ 在C语言中,什么是链表呀
链表
链表链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,链表比较方便插入和删除操作。
概况
链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer)。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表:顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而顺序表相应的时间复杂度分别是O(logn)和O(1)。使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。在计算机科学中,链表作为一种基础的数据结构可以用来生成其它类型的数据结构。链表通常由一连串节点组成,每个节点包含任意的实例数据(data fields)和一或两个用来指向明上一个/或下一个节点的位置的链接("links")。链表最明显的好处就是,常规数组排列关联项目的方式可能不同于这些数据项目在记忆体或磁盘上顺序,数据的存取往往要在不同的排列顺序中转换。而链表是一种自我指示数据类型,因为它包含指向另一个相同类型的数据的指针(链接)。链表允许插入和移除表上任意位置上的节点,[1]但是不允许随机存取。链表有很多种不同的类型:单向链表,双向链表以及循环链表。链表可以在多种编程语言中实现。像Lisp和Scheme这样的语言的内建数据类型中就包含了链表的存取和操作。程序语言或面向对象语言,如C,C++和Java依靠易变工具来生成链表。
编辑本段特点
线性表的链式存储表示的特点是用一组任意的存储单元存储线性表的数据元素(这组存储单元可以是连续的,也可以是不连续的)。因此,为了表示每个数据元素 与其直接后继数据元素 之间的逻辑关系,对数据元素 来说,除了存储其本身的信息之外,还需存储一个指示其直接后继的信息(即直接后继的存储位置)。由这两部分信息组成一个"结点"(如概述旁的图所示),表示线性表中一个数据元素 。
编辑本段扩展
根据情况,也可以自己设计链表的其它扩展。但是一般不会在边上附加数据,因为链表的点和边基本上是一一对应的(除了第一个或者最后一个节点,但是也不会产生特殊情况)。不过有一个特例是如果链表支持在链表的一段中把前和后指针反向,反向标记加在边上可能会更方便。 对于非线性的链表,可以参见相关的其他数据结构,例如树、图。另外有一种基于多个线性链表的数据结构:跳表,插入、删除和查找等基本操作的速度可以达到O(nlogn),和平衡二叉树一样。 其中存储数据元素信息的域称作数据域(设域名为data),存储直接后继存储位置的域称为指针域(设域名为next)。指针域中存储的信息又称做指针或链。 由分别表示,,…, 的N 个结点依次相链构成的链表,称为线性表的链式存储表示,由于此类链表的每个结点中只包含一个指针域,故又称单链表或线性链表.
编辑本段三个链表函数(C语言描述)
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
struct Node{
int data;//数据域
struct Node * next;//指针域
}; /************************************************************************************** *函数名称:insert
*函数功能:在链表中插入元素. *输入:head 链表头指针,p新元素插入位置,x 新元素中的数据域内容 *输出:无 *************************************************************************************/ void insert(Node * head,int p,int x)
{ Node * tmp = head; //for循环是为了防止插入位置超出了链表长度 for(int i = 0;i<p;i++)
{
if(tmp == NULL)
return ;
if(i<p-1)
tmp = tmp->next;
}
Node * tmp2 = new Node;
tmp2->data = x;
tmp2->next = tmp->next;
tmp->next = tmp2;
} /************************************************************************************** *函数名称:del *函数功能:删除链表中的元素 *输入:head 链表头指针,p 被删除元素位置 输出:被删除元素中的数据域.如果删除失败返回-1 **************************************************************************************/
int del(Node * head,int p)
{
Node * tmp = head;
for(int i = 0;i<p;i++)
{
if(tmp == NULL)
return -1;
if(i<p-1)
tmp = tmp->next;
}
int ret = tmp->next->data;
tmp->next = tmp->next->next;
return ret;
}
void print(Node *head)
{
for(Node *tmp = head;
tmp!=NULL; tmp = tmp->next)
printf("%d ",tmp->data);
printf("\n");
}
int main()
{
Node * head;
head = new Node;
head->data = -1;
head->next=NULL;
return 0;
}
编辑本段结语
C语言是学习数据结构的很好的学习工具。理解了C中用结构体描述数据结构,那么对于理解其C++描述,Java描述都就轻而易举了!
编辑本段两种链表形式
一、循环链表 循环链表是与单链表一样,是一种链式的存储结构,所不同的是,循环链表的最后一个结点的指针是指向该循环链表的第一个结点或者表头结点,从而构成一个环形的链。 循环链表的运算与单链表的运算基本一致。所不同的有以下几点: 1、在建立一个循环链表时,必须使其最后一个结点的指针指向表头结点,而不是象单链表那样置为NULL。此种情况还使用于在最后一个结点后插入一个新的结点。 2、在判断是否到表尾时,是判断该结点链域的值是否是表头结点,当链域值等于表头指针时,说明已到表尾。而非象单链表那样判断链域值是否为NULL。
二、双向链表 双向链表其实是单链表的改进。 当我们对单链表进行操作时,有时你要对某个结点的直接前驱进行操作时,又必须从表头开始查找。这是由单链表结点的结构所限制的。因为单链表每个结点只有一个存储直接后继结点地址的链域,那么能不能定义一个既有存储直接后继结点地址的链域,又有存储直接前驱结点地址的链域的这样一个双链域结点结构呢?这就是双向链表。 在双向链表中,结点除含有数据域外,还有两个链域,一个存储直接后继结点地址,一般称之为右链域;一个存储直接前驱结点地址,一般称之为左链域。
⑸ 计算机c语言中什么是链表
简单来说就是“承上启下”,区别于正常数组,存储的时候不是一连串连续的内存地址。
链表的特点在于结点,struct stu{
int num;
int score;
struct stu *next;
}
这就是一个简单的链表,
上边两个是数据域,最后一个是指针域
指针域交代了下一个数据是存在哪里的,
这样计算机就可以直接去找到了。
这样便于插入和删除,缺点就是同等的空间下,链表存的数据少,因为他多了指针域。
⑹ C语言 链表
pb=(TYPE*) malloc(LEN);这点不明白起什么作用??是什么意思?
是不明白malloc的使用?大致讲来就是分配一个内存空间,因为链表创建需要动态分配内存,改内存空间的大小是LEN 并使pb指向这个内存空间
pf=head=pb; //i=0是输入num和age第一次循环的意思吗?然后return(head),后面=pf是不是多余?ph已经赋值给head啦为何还要赋值给pf?
看清楚for语句下的花括号所包含了多少语句。
for(i=0;i<n;i++)
{
pb=(TYPE*) malloc(LEN);
printf("input Number and Age\n");
scanf("%d%d",&pb->num,&pb->age);
if(i==0)
pf=head=pb;
else pf->next=pb; return(head)
pb->next=NULL;
pf=pb;
}
这个整体是一个循环,第一次循环包括输入语句,以及if语句里的内容,之后的循环包括输入语句及else里的内容。return head是在整个函数执行完毕后才return,也就是将循环体内所有语句全部执行完毕才会return
pf的作用是指向当前链表的尾节点。由于函数需要返回链表的表头head,所以不宜使用head来进行指示,所以采用一个变量pf来进行指示。
else pf->next=pb; // else 好像和head没有什么联系??如何第一次循环之后还有循环呢?并没有赋值给head 怎么return(head)???//
除了i=0时,也就是当第一个节点插入时,head才会被赋值,并且之后的操作不会对其产生改变。因为表头是固定的。第一次循环之后执行else丽的语句,pf->next=pb; 将已有的链表的尾节点的next指针指向刚创建得节点,pb->next=NULL,将当前链表的尾节点的next指针赋为空。pf=pb,将pf再次指向加入新节点之后的链表的尾节点
⑺ c语言链表
指针在x86系统里大小是32位4个字节,在64位系统是8字节大小。指针好比一个盒子,盒子里有个东西也就是它指向的内容,内容是一个实体对象的首地址。盒子本身不能存放实体对象,就好比盒子里有张名片,通过名片你可以找到这个人,总不能把人放盒子里吧。
得有这个人然后把找到这个人的名片放盒子里。
⑻ C语言链表概念
struct node
{
int data;
struct node *next;
}
这个是一个链表的定义,next就是本身的一个指针
可以这么理解,链表就是一串珠子,每个珠子就是一个结构体,next就是串珠子的线
⑼ c语言链表的用途是什么
1、链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,链表比较方便插入和删除操作。
2、例程:
/*
*对链表的综合操作
*功能有建立,排序,插入,删除,输出
*/
#include<stdio.h>
#include<malloc.h>
typedefintElemType;
typedefstructNodeType
{
ElemTypedata;
structNodeType*next;
}NodeType,*LinkType;
LinkTypecreate()
{//建立链表,返回链表的首地址,头结点没有数据
LinkTypehead,p1,p2;
head=(LinkType)malloc(sizeof(NodeType));
p1=head;
while(p1->data!=0)//当data=0时链表结束
{
p2=p1;
p1=(LinkType)malloc(sizeof(NodeType));
printf("Enterstudent'sinformation: data=");
scanf("%d",&p1->data);
p2->next=p1;
}
p2->next=NULL;
free(p1);
return(head);
}
voidoutput(LinkTypehead)
{//链表的输出,接收链表的首地址
head=head->next;
while(head!=NULL)
{
printf("data=%d ",head->data);
head=head->next;
}
}
LinkTypesort(LinkTypehead)
{//链表排序,接收链表首地址,返回链表首地址
LinkTypeph,p1;
ElemTypetemp;
ph=head->next;
p1=head->next;
while(p1->next!=NULL)//冒泡法
{
ph=head;
while(ph->next!=NULL)
{
if(ph->data>ph->next->data)//按data由小到大排序
{
temp=ph->data;
ph->data=ph->next->data;
ph->next->data=temp;
}
ph=ph->next;
}
p1=p1->next;
}
return(head);
}
LinkTypedel(LinkTypehead)
{//删除结点,接收链表的首地址,返回链表的首地址
ElemTypeDelData;
LinkTypeph,p;
ph=head->next;
printf("Enterthedatayouwanttodel: DelData=");
scanf("%d",&DelData);
while(ph!=NULL&&ph->data!=DelData)//寻找要删除的结点
{
p=ph;
ph=ph->next;
}
if(ph==NULL)//没有找到要删除的结点
{
printf("Entererror! ");
return(head);
}
else
{
if(ph==head->next)//删除头结点
{
head->next=ph->next;
}
else//删除其它结点
{
p->next=ph->next;
}
}
free(ph);
return(head);
}
LinkTypeinsert(LinkTypehead)
{//插入结点,接收链表首地址,返回链表首地址
LinkTypeph,p,insert,temp;
insert=(LinkType)malloc(sizeof(NodeType));
printf("Enterthedatayouwanttoinsert: data=");
scanf("%d",&insert->data);
ph=head->next;
while(ph!=NULL&&ph->data<insert->data)//寻找插入的位置
{
p=ph;
ph=ph->next;
}
if(head->next->data>insert->data)//插入头部
{
temp=head->next;
head->next=insert;
insert->next=temp;
}
else//插入到其它地方
{
p->next=insert;
insert->next=ph;
}
return(head);
}
voidmain()
{
LinkTypehead;
head=create();
output(head);
printf(" ");
head=sort(head);
output(head);
printf(" ");
head=del(head);
output(head);
printf(" ");
head=insert(head);
output(head);
}
⑽ C语言链表操作
包括链表的创建删除添加和释放操作!!
#include<stdio.h>
#include<stdlib.h>
struct node *create();
void print_list(struct node *head);
struct node * insert_node(struct node *h,int x,int y);
struct node * delete_node(struct node *h,int z);
void shifang(struct node *head);
struct node
{
char data;
struct node *next;
};
void main()
{
struct node *head;
int x,y,z;
head=create();
print_list(head);
printf("\n输入插入结点的位置的值和插入的数值:");
scanf("%d%d",&x,&y);
head=insert_node(head,x,y);
print_list(head);
printf("\n输入要删除的结点:");
scanf("%d",&z);
head=delete_node(head,z);
print_list(head);
printf("\n释放链表.\n");
}
struct node *create() //建立链表函数
{
printf("请输入各节点(以-1结尾):\n");
int x;
//定义指针*head,*tail,*s;
struct node *head,*tail,*s;
//head和tail初始化,生成一个头结点
head=tail=(struct node *)malloc(sizeof(struct node));
//在循环中,生成新结点、赋值、连接、尾指针后移
scanf("%d",&x);
while(x!=-1)
{
s=(struct node *)malloc(sizeof(struct node));
s->data=x;
tail->next=s;
tail=s;
scanf("%d",&x);
}
//尾结点的指针域赋NULL
tail->next=NULL;
return head;
}
void print_list(struct node *head) //输出链表函数
{
//定义工作指针*p并赋初值p=head->next;即指向第一个结点
struct node *p;
p=head->next;
//判断链表是否为空,空:输出空表的信息,否则:输出所有结点
if(p==NULL)
printf("The list is NULL.");
else
//在循环中输出当前结点,工作指针后移
{
printf("head->");
while(p!=NULL)
{
printf("%d->",p->data);
p=p->next;
}
printf("end.");
}
}
struct node * insert_node(struct node *h,int x,int y) //添加结点函数
{
struct node *p,*q,*s;
//生成要插入的新结点
s=(struct node *)malloc(sizeof(struct node));
s->data=y;
q=h;
p=h->next;
//查找要插入结点的位置
while((p!=NULL)&&(p->data!=x))
{
q=p;
p=p->next;
}
//插入结点
q->next=s;s->next=p;
return(h);
}
struct node * delete_node(struct node *h,int z) //删除结点函数
{
struct node *p,*q;
q=h;
p=h->next ;
//查找要删除结点的位置
if(p!=NULL)
{
while((p!=NULL)&&(p->data!=z))
{
q=p;
p=p->next;
}
//释放结点
if(p->data ==z)
{
q->next=p->next ;
free(p);
}
}
return(h);
}
void shifang(struct node *head) //释放链表函数
{
struct node *p;
//逐个释放结点
while(head!=NULL)
{
p=head;
head=head->next;
free(p);
}
}