今天在网上看到链表的建立方法,之前不懂双向链表,循环链表怎么建立,这次一看,觉得方法都通用的,其实就是一种方法,所以把这些分享出来,希望对那些对链表有所惧怕的朋友有所帮助。
这部分链表的建立都是固定长度的,利用三个指针pHead,pNew,pEnd 来构造的,在单向链表和双向链表中,头指针不是有效值,它指向的值才是有效的值,也就是说头指针里面的值一般为空,只有指针域里面有指向下一个结构体的地址;但是循环链表就不能这样了,循环链表中每个指针包括头指针也是有效值的,注意一下。源码都经过测试,可用。
1).下面首先是单向链表的建立方法:
#include<stdio.h>
#include<malloc.h>
/**************************************************
定义了一个结构体类型,并未实际分配内存空间只有定义
了变量才分配内存空间
**************************************************/
struct LNode
{
int data;
struct LNode *next;
};
/*************************************************
创建一个单链表,n为要创建的节点个数,pHead为
头指针,没有指向实质数据,只保存第一个节点的地址;
pNew 指针总是用来指向新分配的内存空间,pEnd总是指
向尾节点,并通过pEnd来链入新增节点。
*************************************************/
struct LNode *CreatList(int n)
{
int i , a;
struct LNode *pHead,*pNew,*pEnd;
pHead = NULL;
for(i = 1; i <= n; i++)
{
do{
pNew = (struct LNode *)malloc(sizeof(struct LNode));
}while(pNew == 0);
printf("请输入链表中的第%d个数:",i);
scanf("%d",&a);
pNew->data = a;
if(pHead == NULL) /* 指定链表的头指针 */
{
pHead = pNew;
pEnd= pNew;
}
else
{
pEnd->next = pNew;
pEnd = pNew;
}
pEnd->next = NULL; /* 尾结点的后继指针为NULL(空) */
}
return pHead; /*返回链表的头指针*/
}
void main()
{
int n;
struct LNode *pHead , *p;
printf("请输入链表的长度:");
scanf("%d",&n);
pHead = CreatList(n); /*链表的头指针(head)来标记整个链表*/
p = pHead ;
printf("\n链表中的数据:");
while(p) /*直到结点q为NULL结束循环*/
{
printf("%d ",p->data); /*输出结点中的值*/
p = p->next; /*指向下一个结点*/
}
}
2).再者,分享一个双向链表的建立方法,大同小异。
/*题目:创建双向链表
程序分析:双向链表的结点有两个指针域,一个指向其直接后继,另一个指向其直接前驱。其中第一个结点的前驱为NULL
(头结点为第0个结点),最后一个结点的后继为NULL。
代码如下:*/
#include <stdio.h>
#include <string.h>
#include <malloc.h>
typedef struct LNode
{
char name[20];
struct LNode *prior,*next;
}Lnode;
/*双链表的结构定义*/
Lnode *CreatList(int n) /*创建双链表函数*/
{
Lnode *pEnd,*pHead,*pNew;
int i;
do{
pHead = (Lnode *)malloc(sizeof(Lnode)); /*动态分配内存赋予头结点*/
}while(pHead == 0);
pHead->name[0] = '\0'; /*为头结点的内容置空*/
pHead->prior = NULL; /*头结点的前驱和后继置为NULL*/
pHead->next = NULL;
pEnd = pHead; /*将头结点赋值于p,p总是指向链表的最后一个结点*/
for(i = 0; i < n; i++)
{
pNew = (Lnode *)malloc(sizeof(Lnode)); /*动态分配内存*/
pEnd->next = pNew; /*让p结点的后继指向s*/
printf("请输入第%d个同学的名字:",i+1);
scanf("%s",pNew->name);
pNew->prior = pEnd; /*让s结点的前驱指向p结点*/
pNew->next = NULL; /*让s结点的后继指向NULL,s总是指向新分配的结点*/
pEnd = pNew; /*p总是指向链表的最后一个结点*/
}
pEnd->next = NULL; /*双链表的最后一个结点的后继指向NULL*/
return pHead;
}
Lnode *Search(Lnode *pHead,char *find)
{
Lnode *p = NULL; /*用于定位双链表中的结点*/
char *ptemp = NULL;
p = pHead->next;
while(p)
{
ptemp = p->name;
if(strcmp(ptemp,find) == 0) /*strcmp函数比较两个字符串的内容是否相等*/
return p ; /*若找到,返回当前结点*/
else
p=p->next; /*不相等就继续向下查找*/
}
printf("信息未找到,重新查找\n");
return 0;
}
void Delete(Lnode *p)
{
if(p->next != NULL) /*确定要删除的结点是否为最后一个结点,最后一个结
点后继为NULL*/
p->next->prior = p->prior; /*p结点后继的前驱赋予p结点的前驱*/
p->prior->next = p->next; /*p结点前驱的后继赋予p结点的后继*/
free(p); /*释放p结点的内存空间*/
}
void Dis(Lnode *p) /*输出双链表*/
{
while(p)
{
printf("%s ", p->name);
p = p->next;
}
}
void main()
{
int number;
char sname[20];
Lnode *pHead = NULL ,*sp = NULL; /*head用来标记双链表,sp用来定
位结点*/
printf("请输入链表的长度:");
scanf("%d",&number);
pHead = CreatList(number);
sp = pHead->next; /*sp指向双链表的第一个结点(头结点为第0个结点)*/
printf("双链表内的数据为:");
Dis(sp); /*输出链表*/
printf("\n请输入要查找的学生姓名:");
do{
scanf("%s",sname);
sp = Search(pHead,sname); /*查找链表中的结点*/
}while(sp == 0);
printf("你想要删除的名字是:%s",sp->name);
Delete(sp); /*删除sp结点*/
sp = pHead->next;
printf("\n现在的双链表是:");
Dis(sp); /*输出链表*/
printf("\n");
}
3).最后分享一个循环链表,希望对大家有所帮助。
/*
题目:创建循环链表
程序分析:循环链表与普通链表的操作基本一致,
只是链表中最后一个结点的指针域指向头结点,是链表形成一个环,
从表中的任一结点出发均可找到表中的其它结点
在算法中循环遍历链表是判断条件不再是p->next是否为空,
而是是否等于链表的头指针。
代码如下:
*/
#include<stdio.h>
#include<malloc.h>
typedef struct LNode
{
char num;
struct LNode *next;
}Lnode;
Lnode *CreatList()
{
Lnode *pNew = NULL,*pEnd = NULL,*pHead;
char a;
pHead = NULL; /*新创建的链表的头指针为NULL(空)*/
a = getchar();
while(a != '\n')
{
pNew = (Lnode *)malloc(sizeof(Lnode)); /*动态分配内存空间*/
pNew->num = a; /*为结点的数据域赋值*/
if(pHead == NULL) /*指定链表的头指针*/
pHead = pNew;
else
pEnd->next = pNew; /*将新结点p1链入链表*/
pEnd = pNew; /*pEnd指向刚链入的新结点,即让pEnd始终指向链表的最后一个结点*/
a = getchar();
}
pEnd->next = pHead; /*链表的最后一个结点的后继指向头结点*/
return pHead;
}
void main()
{
Lnode *p = NULL,*pHead = NULL;
printf("请输入循环链表内容:");
pHead = CreatList();
p = pHead;
printf("\n循环链接表:\n");
p = p->next;
while(p != pHead)
{
printf("%c",p->num);
p = p->next;
}
printf("\n");
}
后面有机会的话还会陆续上传一些链表相关的插入,删除,遍历等程序。