静态链表实现

在C语言中,一般的链表使用指针来实现,链表中的每一个结点都包含有指向下一个结点的指针,但在一些语言中没有指针的概念,所以就有了静态链表的概念。静态链表与数组类似,占用连续的存储空间,但在每个结点中存在一个指向下一个结点的游标,静态链表本质上也是一种顺序存取的结构,只不过它使用了数组的形式。对于静态链表来说,它的大小也是固定的,不能像链表一样进行动态分配。

静态链表的形式如上图,每个结点都包含一个指向下一个结点下标的域,对于上图这种链表来说,可以使用结构体数组或者二维数组(两列,一列表示值,一列表示next)来实现。

静态链表的实现代码如下:


#define MAX_SIZE 10

//静态链表使用结构体数组或者二维数组(用第二列来表示下一个元素的下标)
//对于本程序中实现的静态链表,如果使用二维数组实现,只需要将用到value的地方替换为第一列元素,用到next的地方替换为第二列元素
typedef struct ListNode {
	int value;//值域
	int next;//记录下一个数据的下标
}ListNode;

typedef struct staList {
	ListNode value[MAX_SIZE + 1];//下标为0处为表头
	int numofele;//记录当前表中元素的个数
}staList;

staList* CreatList() {

	//根据大小size建立一个能存放size个元素的表
	staList* l = (staList*)malloc(sizeof(staList));
	if (l == NULL) {
		perror("malloc");
		return NULL;
	}

	//初始化表,将下标为0的位置作为表头,next域为-1时就表示该位置没有元素
	l->numofele = 0;
	l->value[0].next = 0;
	for (int i = 1; i <= MAX_SIZE; i++) {
		//用-1表示当前结点为可以插入元素,0表示空指针,因为下标为0处为表头,所以用0表示空指针不会出现问题
		l->value[i].next = -1;
	}

	return l;

}

void DestoryList(staList* l) {
	if (l == NULL) {
		printf("表不存在\n");
		return;
	}
	free(l);
	l = NULL;
}

bool IsEmpty(staList* l) {
	if (l == NULL) {
		printf("表不存在\n");
		return false;
	}
	//当表中元素个数为0时,表为空
	return l->numofele == 0;
}

//找到指定位置的元素,返回该节点下标
int FindPosEle(staList* l, int i) {
	if (l == NULL) {
		printf("表不存在\n");
		return -1;
	}
	//查找位置只能从1到最后一个元素的位置
	if (i<1 || i>l->numofele) {
		printf("查找位置不合法\n");
		return -1;
	}
	int tmp = 0;
	//从表头开始向后寻找i个元素
	while (i--) {
		tmp = l->value[tmp].next;
	}
	return tmp;
}

//找到指定值的元素下标
int FindValueEle(staList* l, int k) {

	if (l == NULL) {
		printf("表不存在\n");
		return -1;
	}
	int tmp = l->value[0].next;
	while (tmp) {
		if (l->value[tmp].value == k)//当该节点的值域k相等时,返回下标
			return tmp;
		tmp = l->value[tmp].next;
	}
	printf("不存在该值\n");
	return -1;

}

//找到表中的空位置
int FindSpacePos(staList* l) {
	if (l == NULL) {
		printf("表不存在\n");
		return -1;
	}
	if (l->numofele >= MAX_SIZE) {
		printf("表已满,不存在空位置\n");
		return -1;
	}
	//找到表中next为-1的一个结点
	for (int i = 1; i <= MAX_SIZE; i++) {
		if (l->value[i].next == -1)
			return i;
	}
	return -1;
}

//在指定位置前插
void PreInsert(staList* l, int object, int k) {

	if (l == NULL) {
		printf("表不存在\n");
		return;
	}
	
	//在表中找到可插入的位置
	int pos = FindSpacePos(l);//pos表示空结点的下标
	if (pos == -1) {
		printf("由于某种原因,无法插入\n");
		return;
	}
	l->numofele++;
	l->value[pos].next = l->value[object].next;
	l->value[object].next = pos;
	l->value[pos].value = l->value[object].value;
	l->value[object].value = k;

}

//在指定位置后插
void BackInsert(staList* l, int object, int k) {

	if (l == NULL) {
		printf("表不存在\n");
		return;
	}

	//在表中找到可插入的位置
	int pos = FindSpacePos(l);
	if (pos == -1) {
		printf("由于某种原因,无法插入\n");
		return;
	}
	l->numofele++;
	l->value[pos].next = l->value[object].next;
	l->value[object].next = pos;
	l->value[pos].value = k;

}

//在第i个位置插入
void Insert(staList* l, int i, int k) {
	if (l == NULL) {
		perror("malloc");
		return;
	}
	if (i<1 || i>l->numofele + 1) {
		printf("插入位置不合法\n");
		return;
	}
	int pos = FindSpacePos(l);
	if (pos == -1) {
		printf("由于某种原因,无法插入\n");
		return;
	}
	l->numofele++;
	l->value[pos].value = k;
	//找到第i个位置的前驱
	i--;
	int tmp = 0;
	while (i--) {
		tmp = l->value[tmp].next;
	}
	l->value[pos].next = l->value[tmp].next;
	l->value[tmp].next = pos;


}

//指定结点删除
int ObjectDelete(staList* l, int object) {
	if (l == NULL) {
		printf("表不存在\n");
		return -1;
	}
	if (IsEmpty(l)) {
		printf("表为空,无法删除\n");
		return -1;
	}
	int ret = l->value[object].value;
	l->numofele--;
	//如果该结点的不是最后一个结点,那么可以删除它的后继,并将后继的值赋给它,否则需要找到前驱
	if (l->value[object].next) {//next不为零,说明不是最后一个结点
		int next = l->value[object].next;
		l->value[object].next = l->value[next].next;
		l->value[object].value = l->value[next].value;
		l->value[next].next = -1;
	}
	else {
		int tmp = 0;
		while (l->value[l->value[tmp].next].next) {
			tmp = l->value[tmp].next;
		}
		l->value[tmp].next = 0;
		l->value[object].next = -1;
	}
	return ret;
}

//指定位置删除
int Delete(staList* l, int i) {
	if (l == NULL) {
		printf("表不存在\n");
		return -1;
	}
	if (IsEmpty(l)) {
		printf("表为空,无法删除\n");
		return -1;
	}
	if (i<1 || i>MAX_SIZE) {
		printf("删除位置不合法\n");
		return -1;
	}
	//找到第i个位置的前驱
	i--;
	int tmp = 0;
	while (i--) {
		tmp = l->value[tmp].next;
	}
	int back = l->value[tmp].next;
	int ret = l->value[back].value;
	l->value[tmp].next = l->value[back].next;
	l->value[back].next = -1;
	return ret;
}

//修改指定位置或指定结点的值,逻辑是相同的,这里实现修改指定位置的值
void Revise(staList* l, int i, int k) {
	if (l == NULL) {
		printf("表不存在\n");
		return;
	}
	int pos = FindPosEle(l, i);
	if (pos == -1) {
		printf("位置不合法\n");
		return;
	}
	l->value[pos].value = k;
}

//打印表中结点
void Print(staList* l) {
	if (l == NULL) {
		printf("表不存在\n");
		return;
	}
	if (IsEmpty(l)) {
		printf("表为空,无法打印\n");
		return;
	}
	int tmp = l->value[0].next;
	while (tmp) {
		printf("%d ", l->value[tmp].value);
		tmp = l->value[tmp].next;
	}
	printf("\n-----------------------------\n");
}

测试代码:

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>

int main() {

	staList* l = CreatList();

	for (int i = 0; i < 5; i++) {
		Insert(l, i + 1, i);
	}
	Print(l);

	Delete(l, 5);
	Print(l);

	return 0;
}

静态链表是一种基于数组的链表实现方式,它可以在不使用指针的情况下实现链表的基本操作。静态链表实现归并排序的基本思路是将数组分成若干个小的有序数组,然后将这些有序数组两两合并,直到最终得到一个完整的有序数组。 以下是静态链表实现归并排序的步骤: 1. 定义静态链表结构体,包含数据和指向下一个元素的指针。 2. 定义归并排序函数,该函数接收一个静态链表作为参数。 3. 在归并排序函数中,首先判断链表是否为空或只有一个元素,如果是,则直接返回。 4. 如果链表中有多个元素,则将链表分成两个部分,分别递归调用归并排序函数。 5. 在递归调用结束后,将两个有序链表合并成一个有序链表。 6. 合并两个有序链表的方法是,比较两个链表的头元素,将较小的元素插入到新链表中,并将指针指向下一个元素。 7. 最后返回新链表。 以下是静态链表实现归并排序的Python代码示例: ```python class Node: def __init__(self, val, next=None): self.val = val self.next = next def merge_sort(head): if not head or not head.next: return head mid = get_mid(head) right = mid.next mid.next = None left = head left = merge_sort(left) right = merge_sort(right) return merge(left, right) def get_mid(head): if not head: return head slow = head fast = head while fast.next and fast.next.next: slow = slow.next fast = fast.next.next return slow def merge(left, right): dummy = Node(0) cur = dummy while left and right: if left.val < right.val: cur.next = left left = left.next else: cur.next = right right = right.next cur = cur.next if left: cur.next = left if right: cur.next = right return dummy.next ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值