数据结构 C语言版_严蔚敏,李冬梅,吴伟民编著--线性表课后习题

线性表

需要有顺序表和链表的基本了解,这里不再赘述,如有错误欢迎指正。

一、算法设计题目

  1. 将两个递增的有序链表合并为一个递增的有序链表。要求结果链表仍使用原来两个链表 的存储空间,不另外占用其他的存储空间。表中不允许有重复的数据。
  2. 将两个非递减的有序链表合并为一个非递增的有序链表。要求结果链表仍使用原来两个 链表的存储空间,不另外占用其他的存储空间。表中允许有重复的数据。
  3. 已知两个链表 A 和 B 分别表示两个集合,其元素递增排列。请设计一个算法,用于求出A 与 B 的交集,并存放在 A 链表中。
  4. 巳知两个链表 A 和 B 分别表示两个集合,其元素递增排列。请设计算法求出两个集合 A 和 B 的差集(即仅由在 A 中出现而不在 B 中出现的元素所构成的集合),并以同样的形式存储, 同时返回该集合的元素个数。
  5. 设计算法将一个带头结点的单链表 A 分解为两个具有相同结构的链表 B 和 C, 其中 B 表的结点为 A 表中值小于零的结点,而 C 表的结点为 A 表中值大于零的结点(链表 A 中的元素 为非零整数,要求 B 、 C 表利用 A 表的结点)。
  6. 设计一个算法,通过一趟遍历确定长度为 n 的单链表中值最大的结点。
  7. 设计一个算法,将链表中所有结点的链接方向“原地”逆转,即要求仅利用原表的存储 空间,换句话说,要求算法的空间复杂度为 0(1) 。
  8. 设计一个算法,删除递增有序链表中值大于 mink 且小于 maxk:的所有元素( mink 和 maxk 是给定的两个参数,其值可以和表中的元素相同,也可以不同)。
  9. 巳知p指向双向循环链表中的一个结点,其结点结构为 data、prior 、 next三个域,写出算法 change(p),交换p所指向的结点及其前驱结点的顺序。
  10. 已知长度为 n 的线性表 A 采用顺序存储结构,请写一个时间复杂度为 O(n) 、空间复杂度为 0(1)的算法,该算法可删除线性表中所有值为item 的数据元素。

二、具体实现

1.基本结构和操作

注:以下链表皆带头结点。

  1. 单链表(带头结点)基本结构和基本操作

    /**
     * \brief 数据域类型
     */
    typedef int ElemType;
    
    /**
     * \brief 单链表
     */
    typedef struct Node
    {
    	ElemType data;//数据域
    	struct Node* next;//指向下一结点
    } Node,*LinkedList;
    /**
     * \brief 初始化链表(单链表) 
     * \param list 
     * \return 
     */
    int init(LinkedList* list)
    {
    	(*list) = (Node*)malloc(sizeof(Node));
    	if (!(*list))
    	{
    		printf("链表初始化失败!");
    		return 0;
    	}
    	(*list)->next = NULL;
    	(*list)->data = 0;
    	return 1;
    }
    
    /**
     * \brief 销毁链表(单链表)
     * \param list 
     * \return 
     */
    int destroy(LinkedList* list)
    {
    	Node* temp = (*list)->next;
    	while (temp)
    	{
    		Node* next = temp->next;
    		free(temp);
    		temp = next;
    	}
    	free((*list));
    	(*list)=NULL;
    	return 1;
    }
    
    /**
     * \brief 头插法(单链表)
     * \param list 链表
     * \param e 元素
     * \return 
     */
    int insert_head(const LinkedList* list,ElemType e)
    {
    	Node* createNode = (Node*)malloc(sizeof(Node));
    	if (!createNode)
    	{
    		printf("头插法新增结点失败!");
    		return 0;
    	}
    	createNode->data = e;
    	createNode->next = (*list)->next;
    	(*list)->next = createNode;
    	return 1;
    }
    
    /**
     * \brief 尾插法(单链表)
     * \param list 链表
     * \param e 元素
     * \return 是否成功
     */
    int insert_tail(const LinkedList* list, ElemType e)
    {
    	Node* createNode = (Node*)malloc(sizeof(Node));
    	if (!createNode)
    	{
    		printf("尾插法新增结点失败!");
    		return 0;
    	}
    	Node* temp = (*list);
    	while (temp->next)
    	{
    		temp = temp->next;
    	}
    	createNode->next = temp->next;
    	temp->next = createNode;
    	createNode->data = e;
    	return 1;
    }
    /**
     * \brief 打印链表
     * \param list
     * \param msg
     */
    
    void display(const LinkedList* list, const char* msg)
    {
    	printf("打印%s:\n", msg);
    	const Node* temp = (*list)->next;
    	while (temp)
    	{
    		printf("%d ", temp->data);
    		temp = temp->next;
    	}
    	printf("\n");
    }
    /**
     * \brief 计算带头结点的链表的长度
     * \param list 带头结点的链表
     * \return 链表的长度
     */
    int list_length(const LinkedList list)
    {
    	const Node* temp = list->next;
    	int len = 0;
    	while (temp)
    	{
    		len++;
    		temp = temp->next;
    	}
    	return len;
    }
    
  2. 顺序表基本结构和操作

    /**
     * \brief 顺序表最容量
     */
    #define MAXSIZE  100
    
    typedef struct SeqList
    {
    	ElemType data[MAXSIZE];
    	unsigned int len;
    }SeqList;
    
    /**
     * \brief 初始化
     * \param list 顺序表
     * \return 是否成功
     */
    int init_seq_list(SeqList* list)
    {
    	for (int i = 0; i < MAXSIZE; i++)
    	{
    		list->data[i] = 0;//将所有数据元素设置为默认
    	}
    	list->len = 0;//顺序表初始长度为0
    	return 1;
    }
    /**
     * \brief 插入(顺序表)
     * \param list 顺序表
     * \param data 元素
     */
    void insert_seq_list(SeqList* list,ElemType data)
    {
    	if (list->len>=MAXSIZE)
    	{
    		printf("顺序表已满");
    		return;
    	}
    	list->data[(list->len)++]=data;
    }
    
  3. 双向循环链表基本结构和操作

    /**
     * \brief 双向循环链表
     */
    typedef struct DCNode
    {
    	ElemType data;//数据域
    	struct DCNode* prior;//前驱
    	struct DCNode* next;//后继
    } DCNode, * DCLinkedList;
    
    
    /**
     * \brief 双向循环链表初始(带头结点,头结点存储INT_MIN值)
     * \param list 双向链表
     * \return 是否成功
     */
    int initDCLinkedList(DCLinkedList* list)
    {
    	(*list) = (DCNode*)malloc(sizeof(DCNode));
    	if (!(*list))
    	{
    		printf("双向循环链表头结点创建失败");
    		return 0;
    	}
    	(*list)->data = INT_MIN;
    	(*list)->next = (*list);
    	(*list)->prior = (*list);
    	return 1;
    }
    
    /**
     * \brief 销毁双向循环链表
     * \param list 双向链表
     */
    void destroyDCLinkedList(DCLinkedList* list)
    {
    	if (*list == NULL)
    	{
    		return;
    	}
    	DCNode* current = (*list)->next;
    	while (current != (*list))
    	{
    		DCNode* temp = current;
    		current = current->next;
    		free(temp);
    	}
    	free(*list);
    	*list = NULL;
    }
    
    /**
     * \brief 头插法(双向循环链表)
     * \param list 双向循环链表
     * \param data 数据
     * \return 成功或失败
     */
    int insert_head_dc(DCLinkedList* list,ElemType data)
    {
    	DCNode* createNode = (DCNode*)malloc(sizeof(DCNode));
    	if (!createNode)
    	{
    		printf("新增双向循环链表结点失败");
    		return 0;
    	}
    	createNode->data = data;
    	createNode->prior = (*list);
    	createNode->next = (*list)->next;
    	(*list)->next->prior = createNode;
    	(*list)->next = createNode;
    	return 1;
    }
    
    /**
     * \brief 尾插法(双向循环链表)
     * \param list 双向循环链表
     * \param data 数据
     * \return 是否成功
     */
    int insert_tail_dc(DCLinkedList* list, ElemType data)
    {
    	DCNode* createNode = (DCNode*)malloc(sizeof(DCNode));
    	if (!createNode)
    	{
    		printf("新增双向循环链表结点失败");
    		return 0;
    	}
    	createNode->data = data;
    	createNode->next = *list;
    	createNode->prior = (*list)->prior;
    	(*list)->prior->next = createNode;
    	(*list)->prior = createNode;
    	return 1;
    }
    
    /**
     * \brief 打印双向循环链表
     * \param list 双向循环链表
     * \param msg 信息
     */
    void displayDCL(const DCLinkedList* list, const char* msg)
    {
    	printf("打印%s:\n", msg);
    	const DCNode* temp = (*list)->next;
    	while (temp != (*list))
    	{
    		printf("%d ", temp->data);
    		temp = temp->next;
    	}
    	printf("\n");
    }
    
    

2.代码示例

  1. 将两个递增的有序链表合并为一个递增的有序链表。要求结果链表仍使用原来两个链表 的存储空间,不另外占用其他的存储空间。表中不允许有重复的数据。

    /**
     * \brief 将两个递增的有序链表合并为一个递增的有序链表。
     * 要求结果链表仍使用原来两个链表 的存储空间,不另外占用其他的存储空间。表中不允许有重复的数据。
     * \note
     * 如果要实现不占用额外的空间来合并两个有序链表,我们需要在原有链表的基础上进行操作。\n
     * 我们可以遍历两个链表,依次比较节点的值,然后将较小值的节点插入到结果链表中。具体步骤如下:\n
     * 1.用一个新指针 result 指向两个链表的头节点中较小的那个。\n
     * 2.使用两个指针 p1 和 p2 分别遍历两个链表,比较节点的值,并将较小值的节点连接到结果链表上。\n
     * 3.遍历结束后,将剩余链表(如果有的话)直接链接到结果链表的末尾。
     * \param l1 链表1
     * \param l2 链表2
     * \return 是否成功
     */
    void merge_increase(LinkedList list1,LinkedList list2)
    {
    	Node* p1 = list1->next;
    	Node* p2 = list2->next;
    	Node* result = list1; // 新链表的头节点
    	Node* tail = result;   // 新链表的尾节点
    	
    	while (p1 != NULL && p2 != NULL) {
    		if (p1->data < p2->data) {
    			tail->next = p1;
    			p1 = p1->next;
    		}
    		else if (p1->data > p2->data) {
    			tail->next = p2;
    			p2 = p2->next;
    		}
    		else {
    			// 如果两个节点值相等,只插入一个节点
    			tail->next = p1;
    			p1 = p1->next;
    			p2 = p2->next;
    		}
    		tail = tail->next;
    	}
    	
    	// 将剩余链表链接到结果链表的末尾
    	if (p1 != NULL) {
    		tail->next = p1;
    	}
    	if (p2 != NULL) {
    		tail->next = p2;
    	}
    	// 释放 list2 的头节点
    	free(list2);
    }
    
  2. 将两个非递减的有序链表合并为一个非递增的有序链表。要求结果链表仍使用原来两个 链表的存储空间,不另外占用其他的存储空间。表中允许有重复的数据。

    /**
     * \brief 将两个非递减的有序链表合并为一个非递增的有序链表。
     * 要求结果链表仍使用原来两个 链表的存储空间,不另外占用其他的存储空间。表中允许有重复的数据。
     * \param list1 
     * \param list2 
     */
    void merge_decrement(LinkedList list1,LinkedList list2)
    {
    	Node* p1 = list1->next;
    	Node* p2 = list2->next;
    	Node* head = list1;
    	Node* tail = head;
    	while (p1&&p2)
    	{
    		if (p1->data<p2->data)
    		{
    			tail->next = p2;
    			p2 = p2->next;
    		}
    		else if (p1->data>p2->data)
    		{
    			tail->next = p1;
    			p1 = p1->next;
    		}
    		else
    		{
    			tail->next = p1;
    			p1 = p1->next;
    			tail = tail->next;
    			tail->next = p2;
    			p2 = p2->next;
    		}
    
    		tail = tail->next;
    	}
    
    	if (p1)
    	{
    		tail->next = p1;
    	}
    	if (p2)
    	{
    		tail->next = p2;
    	}
    	free(list2);
    }
    
  3. 已知两个链表 A 和 B 分别表示两个集合,其元素递增排列。请设计一个算法,用于求出A 与 B 的交集,并存放在 A 链表中。

    /**
     * \brief 已知两个链表 A 和 B 分别表示两个集合,其元素递增排列。请设计一个算法,用于求出 A 与 B 的交集,并存放在 A 链表中。
     * \note
     * 这个算法的核心思想是使用两个指针 pA 和 pB 分别指向链表 A 和 B 的头节点,然后同时遍历这两个链表。\n
     * 在遍历过程中,我们比较 pA->data 和 pB->data 的值:\n
     * 1.如果 pA->data < pB->data,说明链表 A 中的当前节点的值比链表 B 中的当前节点的值小,
     * 这意味着链表 A 中的当前节点不在交集中,我们需要将其从链表 A 中删除,并释放该节点的内存,然后将 pA 指针向后移动一位;\n
     * 2.如果 pA->data > pB->data,说明链表 B 中的当前节点的值比链表 A 中的当前节点的值小,
     * 这意味着链表 B 中的当前节点不在交集中,我们只需要将 pB 指针向后移动一位;\n
     * 3.如果 pA->data == pB->data,说明链表 A 和 B 中的当前节点的值相等,这意味着该值属于交集,
     * 我们将其添加到结果链表中(即链表 A),然后同时将 pA 和 pB 指针向后移动一位。\n
     * 在遍历结束后,链表 A 中存放的就是 A 和 B 的交集,而链表 B 中不属于交集的节点已经被释放。
     * \param A 链表A
     * \param B 链表B
     */
    void intersection(LinkedList A, LinkedList B) {
    	Node* pA = A->next;
    	Node* pB = B->next;
    	Node* prev = A; // 用于记录交集链表的尾节点
    	while (pA != NULL && pB != NULL) {
    		if (pA->data < pB->data) {
    			// pA 指向的值小于 pB 指向的值,将 pA 指针向后移动
    			Node* temp = pA;
    			pA = pA->next;
    			free(temp); // 释放 A 链表中不在交集中的节点
    		}
    		else if (pA->data > pB->data) {
    			// pA 指向的值大于 pB 指向的值,pB 指针向后移动
    			Node* temp = pB;
    			pB = pB->next;
    			free(temp); // 释放 B 链表中不在交集中的节点
    		}
    		else {
    			// pA 指向的值等于 pB 指向的值,将该值添加到结果链表中,并同时移动 pA 和 pB
    			prev->next = pA;
    			prev = pA;
    			pA = pA->next;
    			Node* temp = pB;
    			pB = pB->next;
    			free(temp); // 释放 B 链表中重复的节点
    		}
    	}
    	// 处理 A 链表剩余的节点,将其置为 NULL
    	prev->next = NULL;
    	// 释放 B 链表剩余的节点
    	while (pB != NULL) {
    		Node* temp = pB;
    		pB = pB->next;
    		free(temp);
    	}
    	// 释放链表 B 的头节点
    	free(B);
    }
    
  4. 巳知两个链表 A 和 B 分别表示两个集合,其元素递增排列。请设计算法求出两个集合 A 和 B 的差集(即仅由在 A 中出现而不在 B 中出现的元素所构成的集合),并以同样的形式存储, 同时返回该集合的元素个数。

    /**
     * \brief 巳知两个链表 A 和 B 分别表示两个集合,其元素递增排列。
     * 请设计算法求出两个集合 A 和 B 的差集(即仅由在 A 中出现而不在 B 中出现的元素所构成的集合),并以同样的形式存储,同时返回该集合的元素个数。
     * \param A 链表 A
     * \param B 链表 B
     * \return 差集元素的个数
     */
    int difference(LinkedList A, LinkedList B) {
    	Node* pA = A->next; // 指向链表 A 的第一个节点
    	Node* pB = B->next; // 指向链表 B 的第一个节点
    	Node* prev = A;     // 用于记录差集链表的尾节点的前一个节点
    	Node* tail = prev;  // 用于记录差集链表的尾节点
    	int count = 0;      // 差集元素的个数
    	// 遍历链表 A 和链表 B,构建差集链表
    	while (pA && pB) {
    		if (pA->data < pB->data) {
    			// 如果链表 A 的当前节点的值小于链表 B 的当前节点的值,
    			// 则将链表 A 的当前节点插入到差集链表中
    			tail->next = pA;
    			pA = pA->next;
    			tail = tail->next; // 更新差集链表的尾节点
    			count++;           // 差集元素个数加一
    		}
    		else if (pA->data > pB->data) {
    			// 如果链表 A 的当前节点的值大于链表 B 的当前节点的值,
    			// 则只需要将链表 B 的当前节点丢弃并释放即可
    			Node* tempB = pB;
    			pB = pB->next;
    			free(tempB);
    		}
    		else {
    			// 如果链表 A 和链表 B 的当前节点的值相等,
    			// 则需要将两个链表的当前节点都丢弃
    			Node* tempA = pA;
    			tail->next = pA->next; // 从差集链表中删除链表 A 的当前节点
    			pA = pA->next;         // 移动链表 A 的当前节点指针
    			free(tempA);           // 释放链表 A 的当前节点的内存
    			Node* tempB = pB;
    			pB = pB->next;         // 移动链表 B 的当前节点指针
    			free(tempB);           // 释放链表 B 的当前节点的内存
    		}
    	}
    	// 将链表 A 剩余的节点添加到差集链表中
    	while (pA) {
    		tail->next = pA;
    		pA = pA->next;
    		tail = tail->next;
    		count++; // 差集元素个数加一
    	}
    	// 释放链表 B 头结点的内存
    	free(B);
    	// 返回差集元素的个数
    	return count;
    }
    
  5. 设计算法将一个带头结点的单链表 A 分解为两个具有相同结构的链表 B 和 C, 其中 B 表的结点为 A 表中值小于零的结点,而 C 表的结点为 A 表中值大于零的结点(链表 A 中的元素 为非零整数,要求 B 、 C 表利用 A 表的结点)。

    /**
     * \brief
     * 设计算法将一个带头结点的单链表 A 分解为两个具有相同结构的链表 B 和 C,
     * 其中 B 表的结点为 A 表中值小于零的结点,
     * 而 C 表的结点为 A 表中值大于零的结点(链表 A 中的元素为非零整数,要求 B 、 C 表利用 A 表的结点)。
     * \param A 单链表 A
     * \param B 单链表 B
     * \param C 单链表 C
     */
    void split_list(LinkedList A, LinkedList* B, LinkedList* C) {
    	// 初始化链表 B 和链表 C
    	init(B);
    	init(C);
    	Node* p = A->next;
    	Node* pB = *B; // 指向链表 B 的尾节点
    	Node* pC = *C; // 指向链表 C 的尾节点
    	// 遍历链表 A,根据节点的值将节点插入到链表 B 或链表 C
    	while (p != NULL) {
    		if (p->data < 0) {
    			// 将节点插入到链表 B 中
    			pB->next = p;
    			pB = pB->next;
    		}
    		else {
    			// 将节点插入到链表 C 中
    			pC->next = p;
    			pC = pC->next;
    		}
    		p = p->next;
    	}
    	// 结束链表 B 和链表 C
    	pB->next = NULL;
    	pC->next = NULL;
    	free(A);
    }
    

6.设计一个算法,通过一趟遍历确定长度为 n 的单链表中值最大的结点。

/**
 * \brief 设计一个算法,通过一趟遍历确定长度为 n 的单链表中值最大的结点。
 * \param list 带头结点的单链表
 * \param n 带头结点单链表的长度
 * \return 值最大的节点
 */
Node* find_max_node(const LinkedList list,int n)
{
	if (list == NULL || n <= 0) {
		return NULL;
	}
	Node* max_node = list->next; // 假设第一个节点是值最大的节点
	// 遍历单链表,找到值最大的节点
	Node* current = list->next;
	int count = 1;
	while (current != NULL && count <= n) {
		if (current->data > max_node->data) {
			max_node = current; // 更新最大节点
		}
		current = current->next;
		count++;
	}
	return max_node;
}
  1. 设计一个算法,将链表中所有结点的链接方向“原地”逆转,即要求仅利用原表的存储 空间,换句话说,要求算法的空间复杂度为 0(1) 。

    /**
     * \brief 设计一个算法,将链表中所有结点的链接方向“原地”逆转,即要求仅利用原表的存储 空间,换句话说,要求算法的空间复杂度为 0(1) 。
     * \param list 单链表
     */
    void reverse(LinkedList* list)
    {
    	//如果链表为空直接返回
    	if (!(*list)->next||!(*list))
    	{
    		return;
    	}
    	Node* current = (*list)->next;
    	Node* next = current->next;
    	while (next)
    	{
    		current->next = next->next;
    		next->next = (*list)->next;
    		(*list)->next = next;
    		next = current->next;
    	}
    }
    
  2. 设计一个算法,删除递增有序链表中值大于 mink 且小于 maxk:的所有元素( mink 和 maxk 是给定的两个参数,其值可以和表中的元素相同,也可以不同)。

    /**
     * \brief 设计一个算法,删除递增有序链表中值大于 mink 且小于 maxk:的所有元素( mink 和 maxk 是给定的两个参数,其值可以和表中的元素相同,也可以不同)。
     * \note
     * 该算法可以分为以下几个步骤:\n
    	1.初始化一个指针(我们可以称之为prev),让它指向链表的头结点。这样可以方便地处理要删除的节点是链表中第一个节点的情况。\n
    	2.使用另一个指针(称为current)遍历链表,从头结点的下一个节点开始(即链表的第一个实际数据节点)。\n
    	3.检查current指针指向的节点的data值是否在mink和maxk之间。如果是,就删除这个节点,同时保持prev指针不变,将current指针移动到下一个节点。\n
    	4.如果current指针指向的节点的data值不在mink和maxk之间,则两个指针同时向后移动。\n
    	5.重复步骤3和4,直到current指针到达链表的末尾。\n
    	优化:\n
    	1.提前终止:当当前节点的值大于等于maxk时,可以立即停止遍历,因为后续的所有节点都不会满足删除条件。\n
    	提前终止的条件:当当前节点的值大于或等于maxk时,循环会停止。这意味着,一旦遇到一个节点的值不小于maxk,
    	函数就不会继续遍历链表的剩余部分,从而提高效率。这在处理长链表时尤其有用,可以减少对链表尾部不满足条件节点的不必要遍历。\n
     * \param list 链表
     * \param mink 最小值
     * \param maxk 最大值
     */
    void deleteRange(LinkedList* list, ElemType mink, ElemType maxk) {
    	if (mink > maxk)
    	{
    		printf("参数错误!\n");
    		return;
    	}
    	if ((*list) == NULL || (*list)->next == NULL) return;
    
    	Node* prev = (*list), * current = (*list)->next;
    
    	while (current != NULL && current->data < maxk) { // 提前终止条件
    		if (current->data > mink) {
    			prev->next = current->next; // 删除当前节点
    			free(current);
    			current = prev->next; // 移动到下一个节点
    		}
    		else {
    			prev = current; // 如果当前节点的值不满足删除条件,移动prev
    			current = current->next; // 移动current
    		}
    	}
    }
    
  3. 巳知p指向双向循环链表中的一个结点,其结点结构为 data、prior 、 next三个域,写出算法 change(p),交换p所指向的结点及其前驱结点的顺序。

    /**
     * \brief 巳知p指向双向循环链表中的一个结点,其结点结构为 data、prior 、 next三个域,写出 算法 change(p),交换p所指向的结点及其前驱结点的顺序。
     * \param p 
     */
    void change(DCNode* p) {
    	//如果是空表或者只有一个结点不需要交换
    	if (p->prior == p || p->next == p||p->data==INT_MIN)
    	{
    		return;
    	}
    	DCNode* pPrior = p->prior; // p的前驱节点
    	DCNode* pPriorPrior = pPrior->prior; // p的前驱的前驱节点
    	DCNode* pNext = p->next; // p的后继节点
    
    	//如果前驱结点是头结点,跳过头结点,反之不需要
    	if (pPrior->data==INT_MIN)
    	{
    		//pPriorPrior的前驱结点的后继指向p
    		pPriorPrior->prior->next = p;
    
    		p->prior = pPriorPrior->prior;
    		p->next = pPrior;
    		pPrior->prior = p;
    		pPrior->next = pPriorPrior;
    		pPriorPrior->prior = pPrior;
    		pPriorPrior->next = pNext;
    
    		//pNext的前驱结点的后继指向p
    		pNext->prior = pPriorPrior;
    	}
    	else
    	{
    		// 将p的前驱的前驱节点的next指向p
    		pPriorPrior->next = p;
    		p->prior = pPriorPrior;
    		
    		// 将p的后继节点的prior指向p的前驱
    		pNext->prior = pPrior;
    		pPrior->next = pNext;
    		
    		// 将p与其前驱节点相互连接
    		p->next = pPrior;
    		pPrior->prior = p;
    	}
    }
    
  4. 已知长度为 n 的线性表 A 采用顺序存储结构,请写一个时间复杂度为 O(n) 、空间复杂度为 0(1)的算法,该算法可删除线性表中所有值为item 的数据元素。

    /**
     * \brief 已知长度为 n 的线性表 A 采用顺序存储结构,请写一个时间复杂度为 O(n) 、空间复杂 度为 0(1)的算法,该算法可删除线性表中所有值为item 的数据元素。
     * \param list 
     * \param item 
     */
    void delSame(SeqList* list,ElemType item)
    {
    	int index = 0;
    	for (unsigned int i = 0; i < list->len; i++) {
    		if (list->data[i] != item) {
    			list->data[index++] = list->data[i];
    		}
    	}
    	list->len = index;
    }
    
posted @ 2024-04-06 23:04  啦啦啦不想起床  阅读(412)  评论(0)    收藏  举报