链表

  • Post author:
  • Post category:其他



线性表链式存储结构通过“链”建立起数据元素之间的逻辑关系,这种用链接方式的线性表简称链表(Link List),在链表上做插入、删除运算不需要移动数据元素。




顺序表和链表的比较


顺序表的优点:


(1)用数组存储数据元素,操作方法简单,容易实现。


(2)不用为表示结点间的逻辑关系而增加额外的存储开销。


(3)存储密度高。


(4)可以随机访问(使用下标访问)。


顺序表的缺点:


(1)做插入,删除操作时,要大量地移动数据元素,效率比较低。


(2)要占用连续的存储空间,且大小要固定,不适合动态存储。




链表的优点:


(1)插入、删除操作简单


(2)大小可变,适合动态存储。


链表的缺点:


(1)查找效率低。


(2)不支持随机存储。


#include<stdio.h>
#include<stdlib.h>
/*
结点定义 
*/
typedef int ElemType;

typedef struct node{
	ElemType data;			//数据域
	struct node *next; 		//指针域 
}LNode, *LinkList;
 
 /*
 单链表的建立
 单链表的建立有两种方法:在链表的头部插入结点和在链表的尾部插入结点(头插法和尾插法)。 
 */
 //头插法建立单链表
 LinkList creat_LinkList1(){
 	LinkList H = (LinkList)malloc(sizeof(LNode));	//生成头结点。
	LNode *s;
	H->next = NULL;									
	int x;											//设数据元素的类型为int
	scanf("%d", &x);
	while(x != -1){
		s = (LinkList)malloc(sizeof(LNode));
		s->data = x;
		s->next = H->next;
		H->next = s;
		scanf("%d", &x);
	}
	 return H;
 }
 //尾插法建立单链表
 LinkList creat_LinkList2(){
 	LinkList H = (LinkList)malloc(sizeof(LNode));
 	H->next = NULL;
 	LNode *s, *r = H;
 	int x;
 	scanf("%d", &x);
 	while(x != -1){
 		s = (LinkList)malloc(sizeof(LNode));
 		s->data = x;
 		s->next = r->next;
 		r->next = s;
 		r = s;
 		scanf("%d", &x);
	 }
	 return H;
 } 
 
 
 //求表长
 /*
 思路:设一个指针p和计数器length,初始化使p指向头结点H,j = 0。若p所指结点还有后继结点,
 p向后移动,计数器加1(长度不包括头结点),重复上述过程,直到p->next=NULL为止。 
 */ 
 int length_LinkList(LinkList H){
 	LNode *p = H;
 	int length = 0;
 	while(p->next != NULL){
 		p = p->next;
 		length++;
	 }
	 return length;
 } 
 
 //查找操作
 /*
 按序号查找 
 思路:从链表的第一个元素结点开始判断当前结点是否是dik个,若是,则返回该结点的指针,
 否则继续查找下一个,直到表结束为止。没有第k个节点是返回空。 
 */ 
 LNode * get_LinkList(LinkList H, int k){
 	LNode *p = H;
	 int j = 0;
	 while(p->next != NULL && j < k){
	 	p = p->next;
	 	j++;
	 } 
	 if(j == k){
	 	return p;
	 }else{
	 	return NULL;
	 }
 } 
 /*
 按值查找
 思路:从链表的第一个元素结点开始=,判断当前结点的值是否等于x,若是, 
 返回该结点的指针,否则继续向后查找,直到表结束为止,若查找不到则返回空。 
 */
 LNode * locate_LinkList(LinkList H, ElemType x) {
 	LNode * p = H->next;
 	while(p != NULL && p->data != x){
 		p = p->next;
	 }
	 return p;
 }
 //单链表的插入
 //在单链表H的第i个位置上插入值为x的元素 
 int insert_LinkList(LinkList H, int i, ElemType x){
 	LNode *p, *s;
	p = get_LinkList(H, i-1);
	if(p == NULL){
		printf("插入位置i错误");
		return -1; 
	} else{
		s = (LinkList)malloc(sizeof(LNode));
		s->data = x;
		s->next = p->next;
		p->next = s;
		return 0;
	}
 } 
 //删除操作
 
 int del_LinkList(LinkList H, int i){
 	LinkList p, q;
 	p = get_LinkList(H, i-1);
 	if(p == NULL){
 		printf("第i-1个结点不存在");
 		return -1;
	 }else{
	 	if(p->next == NULL){
	 		printf("第i个结点不存在");
	 		return -1;
		 }else{
		 	q = p->next;
		 	p->next = q->next;
		 	free(q);
		 	return 0;
		 }
	 }
 } 
 //单链表的倒置
/*
思路:链表建立时,采用尾插法建立的链表和输入的顺序相反。 
*/ 
void reverse(LinkList H){
	LNode *p, *q;
	p = H->next;
	H->next = NULL;
	while(p){
		q = p;
		p = p->next;
		q->next = H->next;
		H->next = q;
	}
}  



 void print_LinkList(LinkList H){
 	LinkList p = H->next;
 	while(p != NULL){
 		printf("%d ",p->data);
 		p = p->next;
	 }
	 printf("\n");
 } 
 
int main(void){
	LinkList H = creat_LinkList2();
	print_LinkList(H);
//	int length = length_LinkList(H);
//	printf("%d\n", length);
//	LNode *p = get_LinkList(H, 5);
//	if(p != NULL)
//	printf("%d", p->data);
//	insert_LinkList(H, 4, 4);
//	print_LinkList(H);
//	del_LinkList(H, 4);
	reverse(H);
	print_LinkList(H);
	return 0;
} 







版权声明:本文为xiaoyanol原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。