链表的建立


title: 链表的建立
date: 2019-02-27 08:49:25
tags: 数据结构

【动态链表】

1.创建链表

动态链表使用new delete需要添加头文件stdlib.h同时我们需要注意的是这里配合使用了指向前驱结点的指针pre和指向当前结点的p。通过数据域与指针域进行创建新结点。需要注意的是头结点head的数据域是不存储数据的。以下是基本的动态链表的代码:

#include<stdio.h>
#include<stdlib.h>
struct node {	//链表结点
	int data;
	node* next; 
};
//创建链表
node* create(int Array[]) {
	node *p, *pre, *head;	//pre保存当前结点的前驱结点,head为头结点
	head = new node;	//创建头结点
	head -> next = NULL;	//头结点不需要数据域,指针域初始为null
	pre = head;		//记录pre为head
	for(int i = 0; i < 5; i++) {
		p = new node;	//新建结点
		//将Array[i]赋值给新建的结点作为数据域 也可以从scanf输入
		p->data = Array[i];
		p->next = NULL;	//新建结点的指针域为NULL
		pre->next = p;	//前驱结点的指针域设为当前新建结点的地址
		pre = p;	//把pre设为p,作为下一个结点的前驱结点 
	} 
	return head;	//返回头结点指针 
} 
int main() {
	int Array[5] = {5, 3, 6, 1, 2};
	node* L = create(Array);	//新建链表,返回的头指针head赋值给L
	L = L->next;	//从第一个结点开始有数据域
	while(L != NULL) {
		printf("%d", L->data);
		L = L->next;
	} 
	return 0;
}

输出结果:

53612

2.查找元素

已经有一个链表,如何查找其中是否有给定的元素。要从第一个结点开始直到查找到数字就计数。

int search(node* head, int x) {	//统计次数 
	int count = 0;	//计数器
	node* p = head->next;	//从第一个结点开始查找
	while(p != NULL) {	//只要没有到达链表的结尾
		if(p->data == x) {
			count++;
		} 
		p = p->next;
	} 
	return count;
}

3.插入元素

插入元素要注意的是一定是插入的元素先输入数据指向前驱结点的下一结点后再进行前驱结点指向新插入的结点,不可以颠倒顺序否则会丢失链表段。

void insert(node* head, int pos, int x) {	//pos为插入节点的位置 x为插入的数据 
	node* p = head;
	for(int i = 0; i < pos - 1; i++) {
		p = p->next;	//pos-1是为了使得pre到达插入节点的前一个结点 
	}
	node* q = new node;		//新建结点
	q->data = x;	//新建结点的数据域为x
	q->next = p->next;	//新建结点的下一个结点为p的下一个结点
	p->next = q;	//将前一个结点指向新结点 
}

4.删除结点

删除元素是删除链表上所有值为给定的x,例如链表为53612我需要删除6就使得链表变为5312.

删除操作是这样的进行的:

void del(node* head, int x) {
	node* p = head->next;	//p从第一个结点开始枚举
	node* pre = head;	//pre始终保存的是p的前一个结点
	while(p != NULL) {
		if(p->data == x) {
			pre->next = p->next;
			delete(p);
			p = pre->next; 
		} else {
			pre = p;
			p = p->next;
		}
	} 
}

以上的代码组合起来栗子如下:

#include<stdio.h>
#include<stdlib.h>
struct node {	//链表结点
	int data;
	node* next; 
};
//创建链表
node* create(int Array[]) {
	node *p, *pre, *head;	//pre保存当前结点的前驱结点,head为头结点
	head = new node;	//创建头结点
	head -> next = NULL;	//头结点不需要数据域,指针域初始为null
	pre = head;		//记录pre为head
	for(int i = 0; i < 5; i++) {
		p = new node;	//新建结点
		//将Array[i]赋值给新建的结点作为数据域 也可以从scanf输入
		p->data = Array[i];
		p->next = NULL;	//新建结点的指针域为NULL
		pre->next = p;	//前驱结点的指针域设为当前新建结点的地址
		pre = p;	//把pre设为p,作为下一个结点的前驱结点 
	} 
	return head;	//返回头结点指针 
} 
int search(node* head, int x) {	//统计次数 
	int count = 0;	//计数器
	node* p = head->next;	//从第一个结点开始查找
	while(p != NULL) {	//只要没有到达链表的结尾
		if(p->data == x) {
			count++;
		} 
		p = p->next;
	} 
	return count;
}
void insert(node* head, int pos, int x) {	//pos为插入节点的位置 x为插入的数据 
	node* p = head;
	for(int i = 0; i < pos - 1; i++) {
		p = p->next;	//pos-1是为了使得pre到达插入节点的前一个结点 
	}
	node* q = new node;		//新建结点
	q->data = x;	//新建结点的数据域为x
	q->next = p->next;	//新建结点的下一个结点为p的下一个结点
	p->next = q;	//将前一个结点指向新结点 
}
void del(node* head, int x) {
	node* p = head->next;	//p从第一个结点开始枚举
	node* pre = head;	//pre始终保存的是p的前一个结点
	while(p != NULL) {
		if(p->data == x) {
			pre->next = p->next;
			delete(p);
			p = pre->next; 
		} else {
			pre = p;
			p = p->next;
		}
	} 
}
int main() {
	int Array[5] = {5, 3, 6, 1, 2};
	//创建动态链表 
	node* L = create(Array);	//新建链表,返回的头指针head赋值给L
	node* head;
	head = L;
	L = L->next;	//从第一个结点开始有数据域
	while(L != NULL) {
		printf("%d", L->data);
		L = L->next;
	} 
	//查询操作 
	L = head;
	printf("\n%d", search(L, 3));
	//插入操作 
	L = head;
	insert(L, 3, 1);
	printf("\n");
	L = head->next;
	while(L != NULL) {
		printf("%d", L->data);
		L = L->next;
	} 
	//删除操作 
	printf("\n");
	L = head;
	del(L, 1);
	L = head->next;
	while(L != NULL) {
		printf("%d", L->data);
		L = L->next;
	}
	return 0;
}

输出结果:

53612
1
531612
5362
【静态链表】

动态链表是需要指针建立结点与结点之间的联系。对于一些问题结点的地址是比较小的整数的时候(比如5位数字的地址),就没有必要去建立动态链表,而应该使用方便很多的静态链表。

静态链表实现原理是hash,即通过建立一个结构体数组,并且令数组的下标直接表示为结点的地址,故静态链表是不需要头结点。定义方法:

struct Node {
    typename data;	//数据域
    int next;	//指针域
}node[size];	

在此处的定义,next为一个int型的整数,用于存放下一结点的地址(事实上是数组的下标)。例如,如果初始结点的地址为11111,第二个结点的地址为22222,第三个结点的地址为33333,且第三个结点为链表的末尾,那么整个静态链表可以通过以下的方式连接起来:

node[11111] = 22222;
node[22222] = 33333;
noed[33333] = -1;	//-1对应动态链表中的NULL,表示没有后继结点

静态链表中还需要注意一点,我们需要把结构体类型名称与结构体变量的名称设置为不同的名字(即Node和node),事实上在一般情况下他们是可以相同的,但是由于静态链表是由数组实现的,那么就有可能需要对其进行排序,这个时候如果结构体类型名和结构体变量名相同,sort函数就会报编译出错。因此在使用静态链表的时候,尽量不要把结构体的类型名和结构体变量名称取为同样的名字。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值