[Data structure and algorithm analysis] Reverse linked list and sequence table (source code included, clear ideas)

introduce

  Sequential lists and linked lists are common linear lists in data structures. The main difference between them is the way memory is managed .
  An sequence table (Array) is composed of a series of elements arranged in a certain order. It uses continuous memory space to store data. Sequential tables use an array to store data, and each element in the array can be accessed through a subscript. Sequential tables have the advantages of random access and high space utilization, but when inserting and deleting elements, other elements need to be moved, resulting in low efficiency. Sequential tables are not suitable for use when elements need to be modified frequently.
  Linked list (List) is a dynamic data structure implemented through pointers, which can store any type of data out of order. The elements in the linked list are called nodes, and each node contains data and a pointer to the next node. In contrast, the memory allocation of linked lists is dynamic and does not require planning the array size in advance, which can effectively avoid memory waste. Linked lists can quickly insert and delete nodes, but because insertions and deletions must first be located at specified locations, their access time is longer than that of sequential lists.
  In short, when you need to query the sequence frequently, access internal elements frequently, and store data with a predefined fixed size, using a sequence table may be a more appropriate choice. But when a large number of elements need to be inserted, deleted, and changed and the space size cannot be predicted in advance, the dynamic allocation method of the linked list is more effective.

Implement sequence table reversal

/***************************************
* 函数功能:逆置顺序表
* 函数参数:int*data-表示待逆置的顺序表 int size-表示顺序表的大小
* 函数返回值:无
****************************************/
void reverse(int*data, int size)
{
    
    
	for (int i = 0; i < size / 2; ++i)
	{
    
    
		int temp = data[i];
		data[i] = data[size - i - 1];
		data[size - i - 1] = temp;
	}
}

  In the function body, a for loop occurs, and the number of loops is linearly related to the data size N. In addition, a constant number of assignment operations are performed in the for loop. Therefore, the time complexity of the entire function is O(N). (where N represents the length of the sequence list)
  The space complexity of this function is O(1) (constant level). During the execution of the function, only a constant number of variables (i, temp) are used, and the space used does not increase with the increase of the problem size N, so the space complexity of the function is O(1).
  Therefore, the time complexity of this function is O(N) and the space complexity is O(1).

Implement linked list reversal

core code

/***************************************
* 函数功能:逆置链表
* 函数参数:struct myHead* list待逆置链表
* 函数返回值:无
****************************************/
void reverseList(struct myHead* list)
{
    
    
	struct myNode*p = list->element->next,*q = NULL;
	// 遍历链表
	while (p)
	{
    
    
		// 保存p的后继节点
		struct myNode*temp = p->next;
		// 改变指针指向的位置
		p->next = q;
		q = p;
		p = temp;
	}
	// 保存反转链表的结果
	list->element->next = q;
}

  The core design idea of ​​the algorithm: changing the position pointed by the node pointer in the linked list, that is, changing the position of the predecessor and successor elements.
  If the elements in the linked list are 1, 2, 3, 4, 5, then the reversal process diagram is as follows:
Insert image description here

  This function mainly has two operations: traversing the linked list and reversing the linked list. During the process of traversing the linked list, each node and the data stored in the node need to be accessed and manipulated. Therefore, the time complexity of the function is O(N). (where N represents the length of the linked list)
  The space complexity of the function is O(1). The function only uses constant-level extra space to store some temporary variables, and the space occupied by these variables has nothing to do with the problem size N, so the space complexity of the function can be considered to be O(1).

Some intermediate functions attached to linked lists

  Linked list structure

struct myNode
{
    
    
	int data;
	struct myNode*next;
};

struct myHead
{
    
    
	int size;
	struct myNode*element;
};

  Some basic operations of linked lists, including initialization, adding nodes and outputting linked lists.


/***************************************
* 函数功能:链表初始化
* 函数参数:无
* 函数返回值:无
****************************************/ 
struct myHead*listInit(void)
{
    
    
	// 初始化头结点
	struct myHead*myList = (struct myHead*)malloc(sizeof(struct myHead));
	myList->size = 0;
	// 添加虚拟节点
	myList->element = (struct myNode*)malloc(sizeof(struct myNode));
	myList->element->data = -1;
	myList->element->next = NULL;
	return myList;
}

/***************************************
* 函数功能:使用尾插法插入值至链表中
* 函数参数:struct myHead*list表示目标链表 int data表示待插入的值
* 函数返回值:无
****************************************/
void addNode(struct myHead*list, int data)
{
    
    
	struct myNode*p = list->element;
	// 遍历至待插入节点的前驱节点
	while (p->next)
		p = p->next;
	// 新建节点
	struct myNode*myNode = (struct myNode*)malloc(sizeof(struct myNode));
	myNode->data = data;
	myNode->next = NULL;
	// 插入节点并增加链表节点数量
	p->next = myNode;
	list->size++;
}

/***************************************
* 函数功能:输出链表
* 函数参数:struct myHead* list待输出链表
* 函数返回值:无
****************************************/
void outPutList(struct myHead* list)
{
    
    
	struct myNode *p = list->element->next;
	while (p)
	{
    
    
		printf("%d ",p->data);
		p = p->next;
	}
}

Guess you like

Origin blog.csdn.net/qq_53960242/article/details/131053362