顺序表、单向链表和双向链表

顺序表、单向链表和双向链表


关于循环单向链表和循环双向链表请将鼠标移步 此处点击

1.顺序表

实现代码:

//#pragma once				//作为头文件时加上这行
#include<stdio.h>
#define LIST_MAXSIZE 50		//顺序表最大能存的元素个数
typedef int DataType ;		//元素的数据类型
typedef struct {
	DataType list[LIST_MAXSIZE];
	int size;	//顺序表的元素数量
}SeqList;
/*初始化顺序表,将L->size置为0*/
void ListInit(SeqList* L);
/*判断顺序表是否非空*/
int ListNotEmpty(SeqList* L);
/*在下标为i[0,size]的位置处插入一个元素x,位于该处及该处后的元素依次后移,成功返回1,失败返回0*/
int ListInsert(SeqList* L, int i,DataType x);
/*将下标为i[0,size]的位置元素删除,并把值保存在x中,位于该元素后的依次前移,成功返回1,失败返回0*/
int ListDelete(SeqList* L, int i, DataType *x);
/*放问下标为i[0,size]的位置元素,并把值保存在x中,成功返回1,失败返回0*/
int ListGet(SeqList* L, int i, DataType *x);

void ListInit(SeqList* L)
{
	L->size = 0;
}
int ListNotEmpty(SeqList* q)
{
	if (q->size != 0)return 1;
	else return 0;
}
int ListInsert(SeqList* L, int i, DataType x)
{
	int j=L->size;
	if (i < 0 || i > L->size) {
		printf("插入位置i,参数不合法\n");
		return 0;
	}
	if (L->size == LIST_MAXSIZE) {
		printf("顺序表已满,无法插入\n");
		return 0;
	}
	while (j > i) //把原位于i及之后的位置上的元素右移
	{
		L->list[j] = L->list[j - 1];
		j--;
	}
	L->list[i] = x;	//把x插进去
	L->size++;
	return 1;
}
int ListDelete(SeqList* L, int i, DataType *x)
{
	int j = i + 1;	//记录i元素后一个的下标
	if (!ListNotEmpty(L)) {
		printf("顺序表中元素为空,无元素可删除。\n");
		return 0;
	}
	if (i < 0 || i >= L->size) {
		printf("参数不合法,删除失败。\n");
		return 0;
	}
	*x = L->list[i];	//把删除的元素赋值给*x
	while(j<L->size) 
	{
		L->list[j - 1] = L->list[j];	//将位置i后的元素前移
		j++;
	}
	L->size--;
	return 1;
}
int ListGet(SeqList* L, int i, DataType *x)
{
	if (!ListNotEmpty(L)) {
		printf("顺序表中元素为空,无元素可取。\n");
		return 0;
	}
	if (i < 0 || i >= L->size) {
		printf("参数不合法,取出失败。\n");
		return 0;
	}
	*x = L->list[i];
	return 1;
}

测试函数:

void test()
{
	int i, x;
	SeqList L;	
	ListInit(&L);
	for (i = 0; i < 10; i++)
		ListInsert(&L, i, i);
	printf("将下标为5处的元素删除\n");
	ListDelete(&L, 5, &x);
	printf("被删除的元素为:%d\n", x);
	printf("插入元素10到下标为5处:\n", x);
	ListInsert(&L, 5, 10);
	printf("将链表输出\n");
	for (i = 0; i < L.size ; i++)
	{
		ListGet(&L, i, &x);
		printf("%d ", x);
	}
}

运行结果:
在这里插入图片描述

2.单向链表

实现代码:

//#pragma once				//作为头文件时加上这行
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
typedef int DataType;
typedef struct Node
{
	DataType data;
	struct Node *next;
}LinkedList;

/*以下的第几个结点都不包括头节点,即头结点不计入下标*/

/*初始化链表*/
void ListInit(LinkedList* head);
/*判断链表是否非空*/
int ListNotEmpty(LinkedList* head);
/*返回链表元素个数*/
int ListLength(LinkedList* head);
/*在下标为i[0,size]的位置处插入一个元素x,位于该处及该处后的元素依次后移,成功返回1,失败返回0*/
int ListInsert(LinkedList* head, int i, DataType x);
/*将下标为i[0,size]的位置元素删除,并把值保存在x中,位于该处元素后的元素依次前移,成功返回1,失败返回0*/
int ListDelete(LinkedList* head, int i, DataType *x);
/*放问下标为i[0,size]的位置元素,并把值保存在x中,成功返回1,失败返回0*/
int ListGet(LinkedList* head, int i, DataType *x);
/*撤销单链表的空间*/
void ListDestory(LinkedList* head);

void ListInit(LinkedList* head)
{
	head->next = NULL;
}

int ListNotEmpty(LinkedList* head)
{
	if (head == NULL) {
		printf("头结点为NULL\n");
		return 0;
	}
	if (head->next == NULL)return 0;
	else return 1;
}

int ListLength(LinkedList* head)
{
	int i = 0;
	LinkedList* p = head;
	if (head == NULL) {
		printf("头结点为NULL\n");
		return 0;
	}
	while (p->next != NULL)
	{
		i++;
		p = p->next;
	}
	return i;
}

int ListInsert(LinkedList* head, int i, DataType x)
{
	LinkedList *p = head, *p1 = NULL;
	if (head == NULL) {
		printf("头结点为NULL\n");
		return 0;
	}
	while (p != NULL && i--)	//找到下标为i的结点的前一个结点
		p = p->next;
	if (i != -1) {
		printf("插入参数i不合法\n");
		return 1;
	}
	p1 = (LinkedList*)malloc(sizeof(LinkedList));
	p1->data = x;
	p1->next = p->next;
	p->next = p1;
	return 1;
}

int ListDelete(LinkedList* head, int i, DataType *x)
{
	LinkedList *p = head, *p1 = NULL;
	if (head == NULL) {
		printf("头结点为NULL\n");
		return 0;
	}
	while (p != NULL && i--)	//找到下标为i的结点的前一个结点
		p = p->next;
	if (i != -1) {
		printf("删除参数i不合法\n");
		return 1;
	}
	p1 = p->next;
	*x = p1->data;
	p->next = p1->next;
	free(p1);
}

int ListGet(LinkedList* head, int i, DataType *x)
{
	LinkedList *p = head, *p1 = NULL;
	if (head == NULL) {
		printf("头结点为NULL\n");
		return 0;
	}
	while (p != NULL && i--)	//找到下标为i的结点的前一个结点
		p = p->next;
	if (i != -1) {
		printf("参数i不合法\n");
		return 1;
	}
	p = p->next;
	*x = p->data;
	return 1;
}

void ListDestory(LinkedList* head)
{
	LinkedList *p, *p1 = NULL;
	if (head == NULL) {
		printf("头结点为NULL\n");
		return ;
	}
	p = head->next;
	if (p == NULL)return;
	while (p->next != NULL)
	{
		p1 = p;
		p = p->next;
		free(p1);
	}
	free(p);
}

测试函数:

	int i, x, size;
	//也可用malloc动态申请内存,但是最后要自己调用free释放内存
	LinkedList head;
	ListInit(&head);
	for (i = 0; i < 10; i++)
		ListInsert(&head, i, i);
	printf("将下标为5处的元素删除\n");
	ListDelete(&head, 5, &x);
	printf("被删除的元素为:%d\n", x);
	printf("插入元素10到下标为5处:\n", x);
	ListInsert(&head, 15, 15);	//此行插入不合法 
	ListInsert(&head, 5, 10);
	printf("将链表输出\n");
	size = ListLength(&head);
	for (i = 0; i < size; i++)
	{
		ListGet(&head, i, &x);
		printf("%d ", x);
	}
	ListDestory(&head);

运行结果:
在这里插入图片描述

3.双向链表

实现代码:

//#pragma once				//作为头文件时加上这行
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
typedef int DataType;
typedef struct Node
{
	DataType data;
	struct Node *prior;
	struct Node *next;
}DoublyList;

/*初始化链表,新定义的链表结点必须先初始化*/
void ListInit(DoublyList* head);
/*判断链表是否非空,非空返回1,空返回0*/
int ListNotEmpty(DoublyList* head);
/*返回链表元素个数*/
int ListLength(DoublyList* head);
/*在下标为i[0,size]的位置处插入一个元素x,位于该处及该处后的元素依次后移,成功返回1,失败返回0*/
int ListInsert(DoublyList* head, int i, DataType x);
/*将下标为i[0,size]的位置元素删除,并把值保存在x中,位于该处元素后的元素依次前移,成功返回1,失败返回0*/
int ListDelete(DoublyList* head, int i, DataType *x);
/*放问下标为i[0,size]的位置元素,并把值保存在x中,成功返回1,失败返回0*/
int ListGet(DoublyList* head, int i, DataType *x);
/*撤销单链表的空间*/
void ListDestory(DoublyList* head);

void ListInit(DoublyList* head)
{
	head->prior = NULL;
	head->next = NULL;
}

int ListNotEmpty(DoublyList* head)
{
	if (head == NULL) {
		printf("头结点为NULL\n");
		return;
	}
	if (head->next == NULL)return 0;
	return 1;
}

int ListLength(DoublyList* head)
{
	DoublyList *p = head;
	if (head == NULL) {
		printf("头结点为NULL\n");
		return;
	}
	int i = 0;
	while (p->next != NULL)
	{
		i++;
		p = p->next;
	}
	return i;
}

int ListInsert(DoublyList* head, int i, DataType x)
{
	DoublyList *p = head, *p1 = NULL;
	if (head == NULL) {
		printf("头结点为NULL\n");
		return;
	}
	while (p != NULL && i--)	//找到下标为i的结点的前一个结点
		p = p->next;
	if (i != -1) {
		printf("插入参数i不合法\n");
		return 1;
	}
	p1 = (DoublyList*)malloc(sizeof(DoublyList));
	p1->data = x;
	/*下方代码 将新结点p1加到链表中,位于p后*/
	p1->next = p->next;
	p1->prior = p;
	p->next = p1;
	if (p1->next != NULL)p1->next->prior = p1;	//若插入的元素下标不是链表尾
	return 1;
}

int ListDelete(DoublyList* head, int i, DataType *x)
{
	DoublyList *p = head, *p1 = NULL;
	if (head == NULL) {
		printf("头结点为NULL\n");
		return;
	}
	while (p != NULL && i--)	//找到下标为i的结点的前一个结点
		p = p->next;
	if (i != -1) {
		printf("删除参数i不合法\n");
		return 1;
	}
	p1 = p->next;
	*x = p1->data;
	/*下方代码 将p1从链表中删除*/
	p->next = p1->next;
	if (p1->next != NULL)p1->next->prior = p;	//若插入的元素下标不是链表尾
	free(p1);
	return 1;
}

int ListGet(DoublyList* head, int i, DataType *x)
{
	DoublyList *p = head, *p1 = NULL;
	if (head == NULL) {
		printf("头结点为NULL\n");
		return;
	}
	while (p != NULL && i--)	//找到下标为i的结点的前一个结点
		p = p->next;
	if (i != -1) {
		printf("删除参数i不合法\n");
		return 1;
	}
	p1 = p->next;
	*x = p1->data;
	/*下方代码 将p1从链表中删除*/
	return 1;
}

void ListDestory(DoublyList* head)
{
	DoublyList *p, *p1 = NULL;
	if (head == NULL) {
		printf("头结点为NULL\n");
		return;
	}
	p = head->next;
	if (p == NULL)return;
	while (p->next != NULL)
	{
		p1 = p;
		p = p->next;
		free(p1);
	}
	free(p);
}

测试函数:

void test()
{
	int i, x, size;
	//也可用malloc动态申请内存,但是最后要自己调用free释放内存
	DoublyList head;
	ListInit(&head);
	for (i = 0; i < 10; i++)
		ListInsert(&head, i, i);
	printf("将下标为5处的元素删除\n");
	ListDelete(&head, 5, &x);
	printf("被删除的元素为:%d\n", x);
	printf("插入元素10到下标为5处:\n", x);
	ListInsert(&head, 15, 15);	//此行插入不合法 
	ListInsert(&head, 5, 10);
	printf("将链表输出\n");
	size = ListLength(&head);
	for (i = 0; i < size; i++)
	{
		ListGet(&head, i, &x);
		printf("%d ", x);
	}
	ListDestory(&head);
}

运行结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值