您的位置:首页 > 其它

线性表学习归纳总结三:线性表链式存储 不带头结点

2015-06-10 15:10 483 查看
线性表的链式存储,需要考虑链表是否带有头指针,是不是循环链表,是不是双链表

带有头结点的单链表

循环链表

双链表

不带有头结点的单链表,头指针head直接指向第一个结点,带有头结点的单链表,head指向头结点,头结点的存储结构和后续结点一样,但只使用了头结点的next指针域。
链表存储结构



typedef int datatype;
typedef struct link_node{
datatype info;
struct link_node *next;		//指向下一个结点的link_node指针
}node;

基本运算实现函数
node *init();	//建立一个空的单链表
void display(node *head);	//输出单链表中各个结点的值
node *find(node *head,int i);	//在单链表中查找第i个结点的存放地址
node *insert(node *head, datatype x, int i);	//在第i个结点后插入值为x的新结点
node *dele(node *head, datatype x);	//在单链表中删除一个值为x的结点

具体实现函数
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include "slnklist.h"
/************************************************************************/
/* 函数功能:建立一个空的单链表,单链表的初始化   */
/* 函数参数: 无  */
/* 函数返回值: 指向node类型变量的指针  */
/* 文件名: slnklist.c ,函数名:init() */
/************************************************************************/
node *init()
{
return NULL;
}

/************************************************************************/
/* 函数功能: 输出单链表中各个结点的值  */
/* 函数参数:  指向node类型变量的指针head*/
/* 函数返回值: 空  */
/* 文件名: slnklist.c ,函数名: display()*/
/************************************************************************/
void display(node *head)
{
node *p;
p = head;
if (!p)
{
printf("\n单链表是空的!");
}
else
{
printf("\n单链表各个结点的值为:\n");
while(p)
{
printf("%5d",p->info);
p = p->next;
}
}
}

/************************************************************************/
/* 函数功能: 在单链表中查找第i个结点的存放地址  */
/* 函数参数:  指向node类型变量的指针head,int型变量i */
/* 函数返回值:  指向node类型变量的指针 */
/* 文件名: slnklist.c ,函数名: find()*/
/************************************************************************/
node *find(node *head,int i)
{
int j=1;		//结点从1开始计数
node *p = head;
if (i<1)
{
return NULL;
}
while (p && i!=j)
{
p = p->next;
j++;
}
return p;
}
/************************************************************************/
/* 函数功能:  单链表第i个结点后插入值为x的新结点 */
/* 函数参数:  指向node类型变量的指针head,datatype类型变量x,int型变量i	*/
/* 函数返回值:  指向node类型变量的指针 */
/* 文件名: slnklist.c ,函数名: insert()*/
/************************************************************************/
node *insert(node *head, datatype x, int i)
{
node *p,*q;
q = find(head,i);	//第i个结点的存放地址
if (!q && i != 0)
{
printf("\n找不到第%d个结点,不能插入%d!",i,x);
}
else
{
p = (node *)malloc(sizeof(node));	//分配空间
p->info = x;		//设置新结点
if (i==0)	//插入点作为单链表的第一个结点
{
p->next = head;
head = p;
}
else
{
p->next = q->next;
q->next = p;
}
}
return head;
}
/************************************************************************/
/* 函数功能: 在单链表中删除一个值为x的结点 */
/* 函数参数:  指向node类型变量的指针head,datatype类型变量x */
/* 函数返回值:  指向node类型变量的指针 */
/* 文件名: slnklist.c ,函数名: dele()*/
/************************************************************************/
node *dele(node *head, datatype x)
{
node *pre=NULL, *p;
if (!head)
{
printf("单链表是空的!");
return head;
}
p = head;
while (p && p->info!=x)	//没有找到并且没有找完
{
pre=p;
p=p->next;
}
if (!pre && p->info==x)//要删除的是第一个结点
{
head = p->next;
}
else
pre->next = p->next;
free(p);
return head;
}


main验证函数
#include <stdio.h>
#include <stdlib.h>
#include "slnklist.h"

void main(void)
{
node slnklist;
node *p_slnklist;
//初始化单链表
p_slnklist = init();
//利用插入方法建立一个链表
int getin;
int num = 0;
puts("输入插到链表末尾的值");
while ((scanf("%d", &getin))==1)
{
p_slnklist = insert(p_slnklist, getin,num);
num++;
}
display(p_slnklist);	//输出链表结点值

//查找第i个结点的存放地址
node *q;
int i;
puts("\n查找第i个结点的存放地址,输入i值");
while((scanf("%d", &i))==1)
{
q = find(p_slnklist, i);
printf("第%d个结点值是%d,存放地址是%d\n", i, q->info, q);
puts("查找第i个结点的存放地址,输入i值");
}

//在第i个结点后面插入值为x的新结点
int x;
puts("第i个结点后面插入值为x的新结点,输入i和x");
while((scanf("%d,%d", &i, &x))==2)
{
p_slnklist = insert(p_slnklist, x, i);
display(p_slnklist);
puts("\n第i个结点后面插入值为x的新结点,输入i和x");
}

//在单链表中删除一个值为x的结点
puts("输入带删除的结点值x");
while ((scanf("%d", &x))==1)
{
p_slnklist = dele(p_slnklist, x);
display(p_slnklist);
puts("\n输入带删除的结点值x");
}
system("pause");
}

运行结果



Ps:

单链表中查找第i个结点的存放地址时候,需要特别区分,i是否小于1,以及结点计数是否是从1开始
单链表第i个结点插入值为x的新结点,利用查找第i个结点地址的函数进行定位,需要注意,当find函数返回null时候,要判断是因为i为0,还是因为i超出当前链表大小,i值超出链表大小处理如下
if (!q && i != 0)
{
<span style="white-space:pre">	</span>printf("\n找不到第%d个结点,不能插入%d!",i,x);
}

特别注意,插入结点作为链表第一个结点时候的处理
if (i==0)	//插入点作为单链表的第一个结点
{
p->next = head;
head = p;
}
else
{
p->next = q->next;
q->next = p;
}

删除结点时候,需要判断链表是否为空;不为空时候,查找值为x的结点,并在查找过程中,保存该结点的前驱结点的指针;找到值为x的结点后,需要判断该结点是否为链表的第一个结点
if (!pre && p->info==x)//要删除的是第一个结点
{
head = p->next;
}
else
pre->next = p->next;
free(p);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: