数据结构与算法——链表

1. 线性单链表

1.1 抽象定义

  • 类型名

链表。

  • 类型属性

存储一些列项,运行时确定大小,支持元素的快速插入和删除。

  • 类型操作

读取任意节点元素;

在任意节点位置插入元素;

删除已有节点元素;

清空整个链表。

1.2 代码实现

1.2.1 接口定义

如下,接口定义在linklist.h文件中:

//文件名:Linklist.h 
//主要作用:定义链表的数据接口 
#ifndef _LINKLIST_H_
#define _LINKLIST_H_
#include <stdbool.h>

#define OK true
#define ERROR false
typedef int ElemType ;		//定义数据类型 

typedef struct Node{		//定义链表节点 
	ElemType data;
	struct Node* next;
}Node;

typedef struct Node* LinkList;//定义表头节点 

bool GetElem(LinkList L, int i, ElemType* e);		//用e返回链表中第i个结点的元素值 
bool ListInsert(LinkList* L, int i, ElemType* e);	//在链表第i个位置之前插入e
bool ListDelete(LinkList* L, int i, ElemType* e);	//删除链表的第i个结点,用e返回其值
LinkList CreatListhead();							//创建链表头结点;
bool ListDestory(LinkList* L);						//删除整个链表 
void ListPrint(LinkList* L);						//打印输出整个链表的所有元素 
#endif

1.2.2 接口实现

如下,接口实现在linklist.c文件中:

//文件名:linklist.c
//主要作用:链表接口的实现 
#include "linklist.h"
#include <stdlib.h>
#include <stdio.h>
//#define OK true
//#define ERROR false
//typedef int ElemType ;		//定义数据类型 
//
//typedef struct Node{		//定义链表节点 
//	ElemType data;
//	struct Node* next;
//}Node;
//
//typedef struct Node* LinkList;//定义表头节点

//用e返回链表中第i个结点的元素值 
bool GetElem(LinkList L, int i, ElemType* e){
	if(i<1)return ERROR;
	int j=1;
	LinkList p;
	p=L->next;
	for(;j<i;j++){	//寻找第i个节点 
		p=p->next;
		if(!p)return ERROR;	//超出链表范围,return ERROR 
	}
	*e=p->data;		//输出第i个节点 
	return OK;
}		
//在链表第i个位置之前插入e,1<=i<=Length(L)
bool ListInsert(LinkList* L, int i, ElemType* e){
	int j=1;
	LinkList p;
	p=*L;
	for(;j<i;j++){	//寻找第i-1个节点 
		p=p->next;
		if(!p)return ERROR;
	}
	LinkList tmp=(LinkList)malloc(sizeof(Node));
	tmp->data=*e;
	tmp->next=p->next;
	p->next=tmp;
	
	return OK;
}
//删除链表的第i个结点,用e返回其值
bool ListDelete(LinkList* L, int i, ElemType* e){
	int j=1;
	LinkList p;
	p=(*L);
	for(;j<i;j++){	//寻找第i-1个节点 
		p=p->next;
		if(!p)return ERROR;
	}
	LinkList tmp=p->next;	//tmp存放第i个节点 
	*e=tmp->data;			//*e存放第i个节点的值 
	p->next=tmp->next;		//第i-1个节点指向第i+1个节点 
	free(tmp);				//释放第i个节点 
	return OK;
}
//创建链表头结点	
LinkList CreatListhead(){
	LinkList head=(LinkList)malloc(sizeof(Node));
	head->next=NULL;
	return head;
}
//删除整个链表,将L置为空表					
bool ListDestory(LinkList* L){
	LinkList tmp=(*L)->next;
	LinkList p;
	while(tmp){
		p=tmp;
		tmp=tmp->next;
		free(p);
	}
	(*L)->next=NULL;
	return OK;
}
//打印输出整个链表的所有元素 
void ListPrint(LinkList* L){
	LinkList tmp=(*L)->next;
	int i=0;
	if(!tmp){
		printf("The List is empty!\n");
		return;
	}
	while(tmp){
		printf("%-5d",tmp->data);
		tmp=tmp->next;
	}
	printf("\n"); 
}					

1.2.3 主函数调用

注释比较详细,生成随机数矩阵,并将这些元素添加到链表中,测试打印、插入链表节点元素、获得链表节点元素,删除链表等操作。

#include <stdio.h>
#include <stdlib.h>
#include "linklist.h"
#include <time.h>

#define MAXLEN 10
#define MAX 1000
#define MIN 0

int* generateArray(int num);
void displayArray(int* arr,int num);

int main(int argc, char *argv[]) {
	
	LinkList List=CreatListhead();	//调用 CreatListhead创建头结点 
	int* array=generateArray(MAXLEN);	//生成随机数数组 
	displayArray(array,MAXLEN);
	int i=0;
	for(;i<MAXLEN;i++){ //利用生成的随机数数组,调用ListInsert函数,构造单链表 
		ListInsert(&List,1,&array[i]);
	}
	ListPrint(&List);	//打印构造出的单链表 
	//删除头元素,连续5次 
	for(i=0;i<MAXLEN/2;i++){	//测试 ListDelete函数,打印输出 
		int tmp;
		ListDelete(&List,1,&tmp);
		printf("%-5d",tmp); 
	}
	printf("\n");
	int tmp;
	while(GetElem(List,i--,&tmp)){	//测试 GetElem函数,打印输出 
		printf("%-5d",tmp);
	}
	ListDestory(&List);	//最后不忘销毁整个链表,释放malloc分配的内存空间 
	printf("\n");
	return 0;
}

//生成MAX和MIN范围内的包含num个元素的数组
int* generateArray(int num){
    srand((unsigned)time(NULL));
    int* arr=(int*)malloc(sizeof(int)*num);
    for(int i=0;i<num;i++)
        arr[i]=((MAX-MIN+1)*rand()/(RAND_MAX+1.0)+MIN);
    return arr;
}
//打印数组中元素 
void displayArray(int* arr,int num){
    for(int i=0;i<num;i++)
        printf("%-5d",arr[i]);
    printf("\n");
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值