数据结构 —— 第三章 线性表的链式存储

目录

链式存储:

 单链表:

定义:

单链表的C语言描述:

建立一个空的单链表

输出单链表中各个结点的值

在电链表中查找一个值为x的结点:

在单链表中查找第i个结点

插入一个值为x的结点作为单链表的第一个节点

在单链表中第i个结点后插入一个值为x的新结点

在单链表中删除一个值为x的结点

带头结点的单链表

建立一个带头结点的单链表:

建立一个空的单链表:(插曲)

输出带头结点单链表中各个结点的值:

在带头结点的单链表中查找一个值为x的结点:

在带头结点的单链表中查找第i个结点

带头结点单链表的几个插入操作:

 在带头结点的单链表的y结点后插入值为x的结点:

带头结点的单链表删除一个值为x的结点:

循环单链表

循环单链表的定义:

建立一个空的循环单链表

输出循环单链表中各个结点的值:

循环单链表的插入过程如图(无头结点的情况)

循环单链表的插入过程如图(有头结点的情况)

循环单链表的删除过程

双链表

双链表的定义

双链表的C语言实现

双链表结构的C语言描述

建立一个空的双链表

输出双链表中各个结点的值

在双链表查找第i个结点的存储地址

双链表的插入操作

双链表第i个结点之后插入值为x的新结点

双链表的删除操作

链式栈:

链式栈的定义:

链式栈的C语言描述

建立一个空的链式栈

判断链式栈是否为空

读链式栈顶结点的值 

输出链式栈中各个结点的值

向链式栈插入值为x的结点(进栈)

删除链式栈的栈顶结点(出栈)

链式队列

链式队列的定义:

链式栈的C语言描述

建立一个空的链式栈队列

判断链式队列是否为空

输出展示队列中各个结点的值

去的链式队列的队首结点值

向链式队列插入一个值为x的结点

删除链式队列中的队首结点


链式存储:

线性结构中每个结点只有一个前驱和一个后继,设定更关心它的后继,这样在存储时除了存放结点的信息外,只要附设一个指针指向它的后继结点的存放位置。

每个结点的储存位置是:

 单链表:

定义:

单链表中的结点一般含有两个域,一个是存放信息的 info域 ,另一个是指向下一个结点的存放地址指针域next

单链表的C语言描述:

typedef int datatype;
typedef struct link_node{
	datatype info;
	struct link_node *next;
}node; 

建立一个空的单链表

node *init_link_list()
{
	return NULL;
 } 

输出单链表中各个结点的值

void print_link_list(node *head)
{
	node *p;
	p = head;
	if(!p) printf("\n单链表是空的!");
	else
	{
		printf("\n各个结点的值为:\n");
		while(p)
		{
			printf("%5d",p->info);
			p = p->next;
		 } 
	 } 
 } 

在电链表中查找一个值为x的结点:

node *find_num_link_list(node *head,datatype x)
{
	node *p;
	p = head;
	while(p && p -> info != x) p = p -> next;
	return p; 
}

在单链表中查找第i个结点

node *find_pos_link_list(node *head,int i)
{
	int j = 1;
	node *p = head;
	if(i < 1)
	{
		printf("\nerror\n");
		exit(1);
	} 
	while(p &&i != j)
	{
		p = p->next;
		j ++;
	}
	return p;
}

插入一个值为x的结点作为单链表的第一个节点

node *insert_in_front_link_list(node *head,datatype x)
{
	node *p;
	p =(node*)malloc(sizeof(node));    //使用stdlib头文件 
	p->info=x;
	p->next=head;
	head=p;
	return head; 
}

在单链表中第i个结点后插入一个值为x的新结点

node *insert_x_after_i(node *head,datatype x,int i)
{
	node *p , *q;
	q = find_pos_link_(head,i);
	if(!q)
	{
		printf("\n找不到第%d个结点%d,不能进行插入!",i,x);
		exit(0);
		p=(node*)malloc(sizeof(node));
		p->info=x;
		p->next=q->next;
		q->next=p;
		return head;
	}
 } 

在单链表中删除一个值为x的结点

node *delete_num_link_list(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=head->next;//删除第一个节点的情况 
	else pre->next=p->next;
	free(p);
	return head;
}

带头结点的单链表

建立一个带头结点的单链表:
 

node *init_hlink_link_list()
{
	node *head;
	head=(node*)malloc(sizeof(node));
	head->next=NULL;
	return head;
}

建立一个空的单链表:(插曲)

node *init_link_link()
{
	return NULL;
}

输出带头结点单链表中各个结点的值:

void print_hlink_list(node *head)
{
	node *p;
	p=head->next;
	if(!p) printf("\n带头结点单链表是空的!");
	else
	{
		printf("\n带头结点的单链表的各个结点的值为:\n");
		while(p)
		{
			printf("%5d",p->info);
			p=p->next;	
		}
	}
}

在带头结点的单链表中查找一个值为x的结点:

node *find_num_hlink_list(node *head,datatype x)
{
	node *p;
	p=head->next;
	while(p&&p->info!=x) p=p->next;
	return p; 
}

在带头结点的单链表中查找第i个结点

node *find_pos_hlink_list(node *head,int i)
{
	int j=0;
	node *p=head;
	if(i<0)
	{
		printf("\n带头结点的单链表中不存在第%d个结点!",i);
		return NULL; 
	} 
	while(p&&i!=j)
	{
		p=p->next;
		j++;
	}
	return p;
}

带头结点单链表的几个插入操作:

 在带头结点的单链表的y结点后插入值为x的结点:

node *insert_x_after_y(node *head,datatype x,datatype y)
{
	node *q,*p;
	q=find_num_link_list(head,y);
	if(!q)
	{
		printf("\n没有找到值为%d的结点,不能插入%d!",y,x);
		return head;
	}
	p=(node*)malloc(sizeof(node));
	p->info=x;
	p->next=q->next;
	q->next=p;
	return head;
 } 

带头结点的单链表删除一个值为x的结点:

node *delete_num_hlink_list(node *head,datatype x)
{
	node *pre=head,*q;
	q=head->next;
	while(q&&q->info!=x)
	{
		pre=q;
		q=q->next;
	}
	pre->next=q->next;
	free(q);
	return head;
}

循环单链表

循环单链表的定义:

从表中的某个结点开始,只能访问到这个结点及其后面的结点,不能访问到它前面的结点,除非再从首指针指示的结点开始访问。如果希望从表中的任意一个结点开始,都能访问到表中的其他结点,可以设置表中最后一个结点的指针域指向表中的第一个结点。

代码实现

建立一个空的循环单链表

node *init_clink_list()
{
	return NULL;
}

输出循环单链表中各个结点的值:

void display_clink_list(node *head)
{
	node *p;
	if(!head) printf("\n循环单链表是空的!\n");
	else 
	{
		printf("\n循环单链表各个结点的值分别为:\n");
		printf("%5d",head->info);
		p=head->next;
		while(p!=head)
		{
			printf("%5d",p->info);
			p=p->next;
		 } 
	}
}

循环单链表的插入过程如图(无头结点的情况)

node *insert(node *head,datatype x,int i)
{
	node *p,*q,*myrear;
	int j;
	p=(node*)malloc(sizeof(node));
	p->info=x;
	if(i<0) printf("\n无法找到指定的插入位置!");
	free(p);
	return head;
	if(i<0) 
	{
		printf("\n无法找到指定的插入位置!");
		free(p);
		return head;
	}
	if(i==0&&!head)
	{
		p->next=p;
		head=p;
		return head;
	}
	if(i==0&&head)
	{
		myrear=rear(head);
		p->next=head;
		head=p;
		myrear->next=p;
		return head;
	}
	if(i>0&&!head)
	{
		printf("\n无法找到指定的插入位置!");
		free(p);
		return head; 
	}
	if(i>0&&head)
	{
		q=head;
		j=1;
		while(i!=j&&q->next!=head) 
		{
			q=q->next;
			j++;
		}
		if(i!=j)
		{
			printf("\n无法插入");
			free(p);
			return head; 
		}
		else
		{
			p->next=q->next;
			q->next=p;
			return head;
		}
	}
}

循环单链表的插入过程如图(有头结点的情况)

node *insert_x_after_i(node *head,datatype x,int i)
{
	node *p,*q;
	q=find_pos_clink_list(head,i);
	if(!q) printf("\n表中不存在第%d个结点,无法进行插入!\n",i);
	else
	{
		p=(node*)malloc(sizeof(node));
		p->info=x;
		p->next=q->next;
		q->next=p;
	}
	return head;
}

循环单链表的删除过程

node *delete_num_clink_list(node head,datatype x)
{
	node *pre=NULL,*q;
	if(!head)
	{
		printf("\n循环单链表为空,无法进行删除操作!");
		return NULL; 
	}
	q=head;
	while(q->next!=head&&q->info!=x)
	{
		pre=q;
		q=q->next;
	}
	if(q->info!=x) printf("没有找到值为x的结点!",x);
	else
	{
		if(!q=head) 
		{
			pre->next=q->next;
			free(q);
		}
		else if(head->next=head)
		{
			free(q);
			head=NULL;
		}
		else
		{
			pre=head->next;
			while(pre->next!=q) pre=pre->next;
			head=head->next;
			per->next=head;
			free(q); 
		}
	}
	return head;
}

双链表

双链表的定义

如果需要知道一个结点的前驱和后继结点,上述的链式表是不合适的。既然单链表中每个结点有一个指针域指向它的后继结点,那自然地想到再增设一个指针域指向它的前驱结点,这就构成了双链表。

双链表的C语言实现

双链表结构的C语言描述

typedef int datatype;
typedef struct dlink_node
{
	datatype info;
	struct dlink_node *llink ,*rlink;
}dnode;

建立一个空的双链表

dnode *link()
{
	return NULL;
 } 

输出双链表中各个结点的值

void display(dnode *head)
{
	dnode *p;
	printf("\n");
	p=head;
	if(!p) printf("\n双链表是空的");
	else
	{
		printf("\n双链表中各个结点的值为:\n");
		while(p) 
		{
			printf("%5d",p->info);
			p=p->rlink;
		}
	 } 
} 

在双链表查找第i个结点的存储地址

dnode *find(dnode *head , int i)
{
	int j=i;
	dnode *p=head;
	if(i<1) 
	{
		printf("\n第%d个结点不存在!\n",i);
		return NULL;
	}
	while(p&&i!=j)
	{
		p=p->rlink;
		j ++;
	}
	if(!p)
	{
		printf("\n第%d个结点不存在!\n",i);
		return NULL;
	}
	return p;
 } 

双链表的插入操作

双链表第i个结点之后插入值为x的新结点

dnode *insert(dnode *head , datatype x , int i)
{
	dnode *p , *q;
	p=(dnode*)malloc(sizeof(dnode));
	p->info=x;
	if(i==0)
	{
		p->llink=NULL;
		p->rlink=head;
		if(!head)
		{
			head=p; 
		}
		else 
		{
			head->llink=p;
		}
		return head;
	}
	q=find(head,i);
	if(!q)
	{
		printf("第i个结点不存在,无法进行插入",i);
		free(p);
		return head;
	}
	if(q->rlink==NULL)
	{
		p->rlink=q->rlink;
		p->llink=q;
		q->rlink=p;
	}
	else
	{
		p->rlink=q->rlink;
		p->llink=q;
		q->rlink->llink=p;
		q->rlink=p;
	}
	return head;
}

双链表的删除操作

dnode *dele(dnode *head,datatype x)
{
	dnode *q;
	if(!head)
	{
		printf("双链表为空,无法进行操作");
		return head; 
	}
	q=head;
	while(q && q->info!=x) q=q->rlink;
	if(!q)	printf("\n没有找到值为%d的结点!不做删除操作!",x); 
	if(q==head&&head->rlink)
	{
		head=head->rlink;
		head->llink=NULL;
		free(q);
		return head;
	}
	if(q==head&&!head->rlink)
	{
		free(q);
		return NULL;
	}
	else
	{
		if(!q->rlink)
		{
			q->llink->rlink=NULL;
			free(q);
			return head;
		}
		else
		{
			q->llink->rlink=q->rlink;
			q->rlink->llink=q->llink;
			free(q);
			return head;
		}
	}
 } 

链式栈:

链式栈的定义:

栈的链式存储成为链式栈。链式栈就是一个特殊的单链表,对于这种特殊的单链表,它的插入和删除操作规定在单链表的同一端进行。顶指针一般用top表示

链式栈的C语言描述

typedef int datatype;
typedef struct link_node
{
	datatype info;
	struct link_node *next;
}node;

建立一个空的链式栈

node *init()
{
	return NULL;
}

判断链式栈是否为空

int empty(node *top)
{
	return (top?0:1);
 }

读链式栈顶结点的值 

datatype read(node *top)
{
	if(!top)
	{
		printf("\n链式栈是空的!");
		exit(1);
	}
	return(top->info);
} 

输出链式栈中各个结点的值

void display(node *top)
{
	node *p;
	p=top;
	printf("\n");
	if(!p) printf("\n链式栈是空的");
	while(p) 
	{
		printf("%5d",p->info);
		p=p->next;
	 } 
 } 

向链式栈插入值为x的结点(进栈)

node *push(node *top,datatype x)
{
	node *p;
	p=(node*)malloc(sizeof(node));
	p->info=x;
	p->next=top;
	top=p;
	return top;
}

删除链式栈的栈顶结点(出栈)

node *pop(node *top)
{
	node *q;
	if(!top)
	{
		printf("\n链式栈是空的!");
		return NULL; 
	}
	q=top;
	top=top->next;
	free(q);
	return top;
}

链式队列

链式队列的定义:

队列的链式存储成为链式队列。链式队列就是一个特殊的单链表,对于这种特殊的单链表,它的插入和删除曹组规定在单链表不同端进行

链式栈的C语言描述

typedef int datatype;
typedef struct link_node{
	datatype info;
	struct link_node *next;
}node;
//定义队首和队尾指针 
typedef struct{
	node *front,*rear;
}queue;

建立一个空的链式栈队列

queue *init()
{
	queue *qu;
	qu=(queue*)malloc(sizeof(queue));
	qu->front=NULL;
	return qu;
 }

判断链式队列是否为空

int empty(queue qu)
{
	return (qu.front?0:1); 
 } 

输出展示队列中各个结点的值

void display(queue *qu)
{
	node *p;
	printf("\n");
	p=qu->front;
	if(!p) printf("\n链式队列是空的!\n");
	while(p)
	{
		printf("%5d",p->info);
		p=p->next;
	}
 }

去的链式队列的队首结点值

datatype read(queue qu)
{
	if(!qu.front)
	{
		printf("\n链式队列是空的!");
		exit(1); 
	}
	return (qu.front->info);
 } 

向链式队列插入一个值为x的结点

queue *insert(queue *qu,datatype x)
{
	node *p;
	p=(node*)malloc(sizeof(node));
	p->info=x;
	p->next=NULL;
	if(qu->front==NULL) qu->front=qu->rear=p;
	else
	{
		qu->rear->next=p;
		qu->rear=p;
	}
	return qu; 
}

删除链式队列中的队首结点

queue *dele(queue *qu)
{
	node *q;
	if(qu->front) 
	{
		printf("队列为空,无法删除!"); 
		return qu;
	}
	q=qu->front;
	qu->front=q->next;
	free(q);
	if(qu->front==NULL) qu->rear=NULL;
	return qu; 
 } 
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值