链表
链表是一个基本数据结构。它由一系列节点组成,每个包含任意数据字段和一个或指向下一个或以前的节点的引用(指针)。 注意:最后一个节点必须值空
比传统阵列的一个链表的主要好处是,挂钩项目的顺序可能会有所不同,在内存中或存储在磁盘上的数据项的顺序,允许项目清单进行不同的顺序遍历。
链表是一个自我指示的数据类型,因为它包含一个指针或链接到另一个相同类型的数据。链表允许在固定时间内的列表中的任何一点插入和删除节点,但不允许随机访问。
Singly-linked list 单链表
链表的最简单的一种是有每一个节点的链路的单链表(或简称SLIST )。如果它是最后一个节点,这个链接点到下一个节点列表中或为空值或空列表。
Doubly-linked list 双链表
一个更复杂的一种链表是一个双向链表或双向链表。每个节点有两个环节:如果它是第一个节点,这一个指向前一个节点,或节点指向一个空值或空列表;如果它是最后一个指向下一个节点,或节点指向一个空值或空列表节点。 由数据段和两部分指针,一部分指向前面的,一部分指向下一个节点组成。
Circularly-linked list 循环链表
在一个循环链表中,第一个和最后一个节点是连在一起的
Forexample:
#include<stdio.h>
#include<malloc.h>// #include <stdlib.h>
#include<string.h>
#defineN 10 //创建10个节点
typedefstruct node //定义结构体,并为其其别名为node
{
char name[20]; //定义结构体变量字符数组name 第一部分:存放的数据段
struct node link; //在结构体内用结构体类型的别名node声明一个指针变量link,link为结构体指针(struct node) 第二部分:节点指针
}stud; //结构体别名stud
创建链表
stud* create(int n) //创建有n个节点的链表,返回链表头结点
{
stud *p,*h,*s; //h代表当前节点并指向当前节点,p代表当前节点的前一个节点,s代表当前节点的下一个节点
//stud*h =NULL;//h指向当前节点(头结点)
//stud*s =NULL;//后节点(指向创建的新节点)
//stud*p =NULL;//p指向创建的新节点的前一个节点
//创建头结点 stud* h;h = NULL;
if((h=(stud *)malloc(sizeof(stud)))==NULL) //在堆上为stud结构体变量s申请空间
{ //如果为NULL,则打印如下信息
printf("Memory allocation fails!"); //输出“内存分配失败!”
exit(0); //无条件正常退出此程序的运行;exit(1)表示因错误导致程序退出
}
//创建成功,初始化头结点
strcpy( h->name, “head” ); //将字符串“head”拷贝给当前节点h的name属性
h->link=NULL; //当前节点h的下一个节点为NULL
p=h; //将h节点的内容赋值给p节点所对应的内容
//创建下一个节点 循环
for(int i=0;i<n-1;i++)
{
if((s= (stud *)malloc(sizeof(stud)))==NULL)
{
printf("Memoryallocation fails!");
exit(0);
}
//创建成功,进行初始化
printf("Please input %dperson name:", i+1);
scanf("%s",s->name);
s->link=NULL; //给节点s的下一个节点赋值为NULL
p->link=s; //将s节点的内容赋值给节点p的下一个节点,即h节点
p=s; //最后将节点s的内容赋值给节点P,用来代替为创建下一个节点的头的内容
让p指向当前创建好的节点(s指向的节点)
}
return(h); //返回当前头节点h
}
创建节点的步骤:
1、 定义变量*h(头结点),*p(指向新节点的上一个节点),*s(指向新节点)
2、 创建头结点并判断是否为空,若创建成功(不为空),初始化头结点。并把头结点h赋值给p。
3、 创建下一个节点。循环语句,继续执行第二步。不再是头节点判断,当前新节点(s)判断。若创建成功(不为空),初始化新结点,并把头结点h赋值给s。
4、 返回当前头结点。
查找元素
stud*search(stud *h, char *x) // 查询某个节点,返回链表头结点
{
stud *p = h; //定义结构体指针变量p并初始化为h,返回p
while(p!=NULL) //当节点p的内容不为NULL,则进行查询操作,直到p的值为NULL
{
if(strcmp(p->name, x)==0) //头结点特殊处理(比较两个字符串name和x(当p->name=x时)。即:两个字符串自左向右逐个比较,直到出现不同的字符或遇‘\0’为止)
return(p); //如果找到相同的字符,则将它返回
else //否则,继续查找下一个节点
p=p->link; //p指向下一个节点
}
if(p==NULL) //如果为NULL,打印输出提示信息,没有搜索到
printf("There is no such a student!");
return p; //最后返回所查询的头节点p
}
删除元素
stud* Delete(stud *h, char *x) //删除某个节点,返回链表头结点h
{
if( h == NULL)
returnNULL;
/*节点h的值不为NULL,进行以下操作*/
stud * p1, *p2; //p2 代表当前要比较的节点,p1代表当前节点的前一个节点
p1=h; //将节点h的值赋值给节点p1
p2=h->link; //将节点h的下一个节点的值赋值给节点p2
if (strcmp( p1->name, x )== 0 ) // (如果节点p1中的值和字符x的值相同,进行释放操作)
{
h =h->link; //将h节点的下一个节点的值赋值给h节点
free(p1); //释放节点p1点在内存中所占的空间
returnh; //返回节头点h
}
else
{
}
while(p2!=NULL) //当节点p2的值不为NULL时,执行以下操作
{
if(strcmp(p2->name,x)==0) //节点p2的值和字符x的值相同,进行释放操作
{
p1->link = p2->link; //p1的下一个节点指向p2的下一个节点
free(p2); //释放p2节点在内存中所占的空间
return h; //返回头节点h
}
else //节点p2的值和字符x的值不同,则继续寻找
{
p1=p2; //将节点p2的值赋值给节点p1
p2=p2->link; //将节点p2下一个的节点的值赋值给p2
}
}
rerun h;
}
插入元素
voidinsert(stud *p) //即在p节点后插入一个节点
{
char stuname[20]; //定义一个字符数组
stud *s; //声明一个指向结构体stud的指针变量s(要插入的节点s)
if((s= (stud *)malloc(sizeof(stud)))==NULL) //在堆上为stud结构体变量s申请空间
{ //如果为NULL,则打印如下信息
printf("Memoryallocation fails!"); //输出内存分配失败
exit(0); //无条件正常退出此程序的运行;exit(1)表示因错误导致程序退出
}
printf("Please input name” );
scanf("%s",stuname); //从键盘上输入一个字符串到stuname
strcpy(s->name,stuname); //字符串拷贝(把stuname 拷贝到s->name)
s->link=p->link; //让节点s指向节点p的下一个节点
p->link=s; //节点p的下一个节点指向节点s
}
释放链表
voidfreeList(stud* head) //释放链表
{
stud* p; //定义一个结构体指针变量p
while( head != NULL) //当头节点head的内容不为NULL时就执行释放操作,直到释放完毕
{
p = head; //将头节点的值赋值给节点p
head = head->link; //将头节点head的下一个节点的内容赋值给头节点head
free(p); //释放节点p
}
}
打印链表
voidprintList(stud* head) //打印链表
{
stud* p; //定义一个结构体指针变量p
p = head; //结构体变量整体赋值,将head的内容赋值给p
int count = 0; //定义整型变量 count,并初始化为0
while(p != NULL) //如果节点p的值不为NULL,则执行打印操作,直到节点p的值为NULL
{
printf("%s\n", p->name); //打印输出节点p的变量name的字符串
p = p->link; //将p节点的下一个节点的值赋值给节点p
count++; //计数器加1
}
}
int main()
{
int number;
char fullname[20];
stud *head,*searchpoint;
number=N;
head=creat(number);
printf("Input thesrearch name:");
scanf("%s",fullname);//通过键盘输入一个字符串到fullname
searchpoint=search(head,fullname);
insert(searchpoint);
char[10] str;
scanf( “%s”, str );
head = delete( head, str );
printList( head );
freeList( head );
return 0;
}
写出程序把一个链表中的接点顺序倒排
typedef struct linknode
{
int data;
struct linknode *next;
}node;
链表逆置
node*reverse(node *head)
{
node *p,*q,*r; //q代表当前节点,p代表当前节点的前一个节点,r代表当前节点的下一个节点
p=head;
q=p->next;
while(q!=NULL)
{
r=q->next;
q->next=p;
p=q;
q=r;
}
head->next=NULL;
head=p;
return head;
}