数据结构之线性表的链式存储实现(附完整代码)

顺序表插入、删除时需要通过移动数据来实现,影响了执行效率。

而链表不要求逻辑上相邻的两个数据元素物理上也相邻,因此对线性表的插入、删除不需要移动数据元素,只需要修改链。

下面介绍带头结点的链式表:

数据结构:

typedef int ElementType;
typedef struct LNode * PtrToLNode;
struct LNode{
	ElementType Data;
	PtrToLNode Next;
};
typedef PtrToLNode Position;//这里的位置是结点的地址 
typedef PtrToLNode List; 

1.初始化:

//初始化
List MakeEmpty(){
	List L;
	L = (List)malloc(sizeof (struct LNode));
	if (!L)
		exit (-1);
	L->Next = NULL;
	return L;
} 

2.求表长

在顺序存储表示的线性表中求表长是一件很容易的事,直接返回Last+1值就可以了,但是在链式存储表示中,需要将链表从头到尾遍历一遍;设一个移动的指针p和计数器cnt,初始化后,p从表的第一个结点开始往后移,同时计数器cnt+1.


//求表长
int Length(List L){
	Position p;
	int cnt = 0;
	p = L->Next;
	while(p){
		p = p -> Next;
		cnt++;
	}
	return cnt;
} 

3.查找(按序号查找FindKth)

对于顺序存储,按序号查找是很直接的事,要得到第k个元素的值,直接取L->Data[k-1]就可以了。而对于链式表就需要采用求表长的思路,从头遍历,判断当前结点是否是第K个,若是,返回该结点的值,否则继续后一个。

//根据指定的位序查找s
int FindKth(List L,int K){
	Position p;
	int cnt = 1;//位序从1开始 
	p = L->Next; 
	while(p&&cnt<K){
		p = p-> Next;
		cnt++;
	}
	if((cnt==K)&&p) printf("您查找的数为:%d\n",p -> Data);
	else printf("您查找数不存在");
}

4.查找(按值查找Find)

按值查找的方法也是从头到尾遍历,直到找到为止

//按值查找 
Position Find(List L,int X){
	Position p;
	p = L->Next; 
	while(p&&p->Data!=X){
		p = p-> Next;
	}
	if(p) printf("查找成功,您查找的数为:%d\n",p->Data);
	else printf("您查找数不存在");
}

5.插入

带头结点的链式表的插入

//插入
List Insert(List L ,ElementType X,int i){
	Position tmp,pre;
	int cnt =0 ;
	pre = L;
	while(pre&&cnt<i-1){
		pre = pre->Next;
		cnt++;
	}
	if(pre==NULL||cnt!=i-1){
		printf("插入位置参数错误\n");
	}
	else{
		tmp = (Position)malloc(sizeof(struct LNode));
		tmp->Data=X;
		tmp->Next=pre->Next;
		pre->Next=tmp;
	}
	
} 

6.删除

删除指定位序i的元素,首先需要找到被删除结点的前一个元素,然后再删除结点并释放空间。

//删除
bool Delete(List L,int i){
	Position tmp,pre;
	int cnt = 0;
	pre = L;
	while(pre&&cnt<i-1){
		pre=pre->Next;
		cnt++;
	}
	if(pre==NULL||cnt!=i-1||pre->Next==NULL){
		printf("删除位置参数错误");
	}
	else{
		tmp = pre->Next;
		pre->Next = tmp->Next;
		free(tmp);
		printf("删除成功"); 
	}
} 

7.遍历链表并输出

void DisLinkList(List L)
{
	List p = L->Next;
	printf("输出链表: "); 
	while (p)
	{
		printf("%d ", p->Data);
		p = p->Next;
	}
}

完整的程序代码:

#include<stdio.h>
#include<stdlib.h>
typedef int ElementType;
typedef struct LNode * PtrToLNode;
struct LNode{
	ElementType Data;
	PtrToLNode Next;
};
typedef PtrToLNode Position;//这里的位置是结点的地址 
typedef PtrToLNode List; 
//初始化
List MakeEmpty(){
	List L;
	L = (List)malloc(sizeof (struct LNode));
	if (!L)
		exit (-1);
	L->Next = NULL;
	return L;
} 

//根据指定的位序查找
int FindKth(List L,int K){
	Position p;
	int cnt = 1;//位序从1开始 
	p = L->Next; 
	while(p&&cnt<K){
		p = p-> Next;
		cnt++;
	}
	if((cnt==K)&&p) printf("您查找的数为:%d\n",p -> Data);
	else printf("您查找数不存在");
}

//按值查找 
Position Find(List L,int X){
	Position p;
	p = L->Next; 
	while(p&&p->Data!=X){
		p = p-> Next;
	}
	if(p) printf("查找成功,您查找的数为:%d\n",p->Data);
	else printf("您查找数不存在");
}

//插入
List Insert(List L ,ElementType X,int i){
	Position tmp,pre;
	int cnt =0 ;
	pre = L;
	while(pre&&cnt<i-1){
		pre = pre->Next;
		cnt++;
	}
	if(pre==NULL||cnt!=i-1){
		printf("插入位置参数错误\n");
	}
	else{
		tmp = (Position)malloc(sizeof(struct LNode));
		tmp->Data=X;
		tmp->Next=pre->Next;
		pre->Next=tmp;
	}
	
} 

//删除
bool Delete(List L,int i){
	Position tmp,pre;
	int cnt = 0;
	pre = L;
	while(pre&&cnt<i-1){
		pre=pre->Next;
		cnt++;
	}
	if(pre==NULL||cnt!=i-1||pre->Next==NULL){
		printf("删除位置参数错误");
	}
	else{
		tmp = pre->Next;
		pre->Next = tmp->Next;
		free(tmp);
		printf("删除成功"); 
	}
} 

//求表长
int Length(List L){
	Position p;
	int cnt = 0;
	p = L->Next;
	while(p){
		p = p -> Next;
		cnt++;
	}
	return cnt;
} 

void DisLinkList(List L)
{
	List p = L->Next;
	printf("输出链表: "); 
	while (p)
	{
		printf("%d ", p->Data);
		p = p->Next;
	}
}

int main(){
	Position pre;
	Position L = MakeEmpty();
	pre = L;
	int i,n,x,len,cz,del;
	//插入 
	scanf("%d",&n);
	for(i=1;i<=n;i++){
		scanf("%d",&x);
		Insert(pre,x,i);
	}
	//输出 
	DisLinkList(pre);
	printf("\n");
	//求表长 
	len = Length(L);
	printf("表长为:%d",len);
	printf("\n");
	//按值查找
	printf("请输入你要按值查找的数:\n");
	scanf("%d",&cz);
	Find(L,cz);
	printf("\n");
	//按序号查找
	printf("请输入你要按序号查找的数的序号:\n");
	scanf("%d",&cz);
	FindKth(L,cz);
	printf("\n");
	//删除
	printf("请输入你要删除的数的下标:\n",del);
	scanf("%d",&del);
	Delete(L,del);
	DisLinkList(pre);
	printf("\n");
	return 0;
}

运行结果:

  • 35
    点赞
  • 212
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
在C语言中,实现线性表链式存储结构可以使用指针来实现链式存储结构是通过节点之间的指针连接来表示线性表中的元素关系。 首先,我们需要定义一个节点结构体,该结构体包含两个成员:数据域和指针域。数据域用于存储节点中的数据,指针域用于指向下一个节点。 ```c // 定义节点结构体 typedef struct Node { int data; // 数据域 struct Node* next; // 指针域,指向下一个节点 } Node; ``` 接下来,我们可以定义一个链表结构体,该结构体包含一个指向头节点的指针。 ```c // 定义链表结构体 typedef struct LinkedList { Node* head; // 头节点指针 } LinkedList; ``` 然后,我们可以实现一些基本的操作函数来对链表进行操作,例如插入、删除、查找等。 1. 插入操作:在链表中插入一个新节点,可以在头部插入或者在指定位置插入。 ```c // 在头部插入新节点 void insertAtHead(LinkedList* list, int data) { Node* newNode = (Node*)malloc(sizeof(Node)); newNode->data = data; newNode->next = list->head; list->head = newNode; } // 在指定位置插入新节点 void insertAtPosition(LinkedList* list, int data, int position) { Node* newNode = (Node*)malloc(sizeof(Node)); newNode->data = data; if (position == 0) { newNode->next = list->head; list->head = newNode; } else { Node* current = list->head; for (int i = 0; i < position - 1 && current != NULL; i++) { current = current->next; } if (current != NULL) { newNode->next = current->next; current->next = newNode; } } } ``` 2. 删除操作:从链表中删除指定位置的节点。 ```c // 删除指定位置的节点 void deleteAtPosition(LinkedList* list, int position) { if (list->head == NULL) { return; } Node* temp = list->head; if (position == 0) { list->head = temp->next; free(temp); return; } for (int i = 0; temp != NULL && i < position - 1; i++) { temp = temp->next; } if (temp == NULL || temp->next == NULL) { return; } Node* nextNode = temp->next->next; free(temp->next); temp->next = nextNode; } ``` 3. 查找操作:在链表中查找指定值的节点。 ```c // 查找指定值的节点 Node* search(LinkedList* list, int value) { Node* current = list->head; while (current != NULL) { if (current->data == value) { return current; } current = current->next; } return NULL; } ``` 这样,我们就可以使用上述定义的结构体和函数来实现线性表链式存储结构了。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值