[데이터 구조 및 알고리즘 분석] 역연결리스트 및 시퀀스 테이블(소스코드 포함, 명확한 아이디어)

소개하다

  순차 목록과 연결 목록은 데이터 구조의 일반적인 선형 목록입니다. 그들 사이의 주요 차이점은 메모리가 관리되는 방식 입니다 .
  시퀀스 테이블(Array)은 일정한 순서로 배열된 일련의 요소들로 구성되며, 데이터를 저장하기 위해 연속적인 메모리 공간을 사용합니다. 순차 테이블은 배열을 사용하여 데이터를 저장하며, 배열의 각 요소는 아래 첨자를 통해 액세스할 수 있습니다. 순차 테이블은 임의 접근이 가능하고 공간 활용도가 높다는 장점이 있지만 요소를 삽입하고 삭제할 때 다른 요소를 이동해야 하므로 효율성이 낮다. 순차 테이블은 요소를 자주 수정해야 하는 경우 사용하기에 적합하지 않습니다.
  연결리스트(List)는 포인터를 통해 구현된 동적 데이터 구조로, 어떤 유형의 데이터라도 순서에 관계없이 저장할 수 있습니다. 연결된 목록의 요소를 노드라고 하며 각 노드에는 데이터와 다음 노드에 대한 포인터가 포함됩니다. 반면, 연결된 목록의 메모리 할당은 동적이며 배열 크기를 미리 계획할 필요가 없으므로 메모리 낭비를 효과적으로 방지할 수 있습니다. 연결 목록은 노드를 빠르게 삽입하고 삭제할 수 있지만 삽입과 삭제는 지정된 위치에 먼저 위치해야 하기 때문에 순차 목록보다 접근 시간이 길다.
  즉, 시퀀스를 자주 쿼리해야 하고, 내부 요소에 자주 액세스해야 하며, 미리 정의된 고정 크기로 데이터를 저장해야 하는 경우 시퀀스 테이블을 사용하는 것이 더 적절한 선택이 될 수 있습니다. 하지만 삽입, 삭제, 변경해야 할 요소가 많아 공간 크기를 미리 예측할 수 없는 경우에는 연결리스트의 동적 할당 방법이 더 효과적입니다.

시퀀스 테이블 반전 구현

/***************************************
* 函数功能:逆置顺序表
* 函数参数: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;
	}
}

  함수 본문에서는 for 루프가 발생하며 루프 수는 데이터 크기 N과 선형적으로 관련됩니다. 또한 for 루프에서는 일정한 수의 할당 작업이 수행됩니다. 따라서 전체 함수의 시간복잡도는 O(N)이다. (여기서 N은 시퀀스 목록의 길이를 나타냅니다.)
  이 함수의 공간 복잡도는 O(1)(상수 수준)입니다. 함수 실행 시 일정한 수의 변수(i, temp)만 사용하고, 문제 크기 N이 커져도 사용되는 공간은 늘어나지 않으므로 함수의 공간 복잡도는 O(1)이다.
  따라서 이 함수의 시간 복잡도는 O(N)이고 공간 복잡도는 O(1)입니다.

연결 목록 반전 구현

핵심 코드

/***************************************
* 函数功能:逆置链表
* 函数参数: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;
}

  알고리즘의 핵심 설계 아이디어: 연결 리스트에서 노드 포인터가 가리키는 위치를 변경하는 것, 즉 선행 요소와 후속 요소의 위치를 ​​변경하는 것입니다.
  연결된 목록의 요소가 1, 2, 3, 4, 5인 경우 반전 프로세스 다이어그램은 다음과 같습니다.
여기에 이미지 설명을 삽입하세요.

  이 함수에는 주로 연결 목록 순회와 연결 목록 역전이라는 두 가지 작업이 있습니다. 연결리스트를 순회하는 과정에서 각 노드와 그 노드에 저장된 데이터에 접근하고 조작해야 한다. 따라서 함수의 시간복잡도는 O(N)이다. (여기서 N은 연결된 목록의 길이를 나타냅니다.)
  함수의 공간 복잡도는 O(1)입니다. 함수는 일부 임시 변수를 저장하기 위해 상수 수준의 추가 공간만을 사용하며, 이러한 변수가 차지하는 공간은 문제 크기 N과 관련이 없으므로 함수의 공간 복잡도는 O(1)로 간주할 수 있습니다.

연결된 목록에 연결된 일부 중간 기능

  연결리스트 구조

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

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

  초기화, 노드 추가 및 연결 목록 출력을 포함한 연결 목록의 일부 기본 작업입니다.


/***************************************
* 函数功能:链表初始化
* 函数参数:无
* 函数返回值:无
****************************************/ 
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;
	}
}

Supongo que te gusta

Origin blog.csdn.net/qq_53960242/article/details/131053362
Recomendado
Clasificación