C++ singly linked list implements factorial (high precision algorithm)

In the high-precision algorithm, there is an example of finding the factorial of a large number in an array, which can also be realized with a singly linked list.

Idea: Each node only stores a one-digit number. After each node is multiplied by the value obtained by the corresponding number, the remainder divided by 10 is assigned to the current node. The quotient obtained by dividing by 10 generates a carry to the next node.

----------------------------------------------------------------------------------------------

Define a singly linked list data structure

#include <iostream>

using namespace std;

typedef struct LNode {
	int data;
	LNode* next;
} LinkList;

1. Initialize the singly linked list

void InitList(LinkList*& L) {
	L = new LinkList;
	L->next = NULL;
}

2. Destroy the singly linked list

void DestroyList(LinkList*& L) {
	LinkList* p = L->next;
	while (p) {
		L->next = L->next->next;
		delete p;
		p = L->next;
	}
	delete L;
}

3. Find the length of the singly linked list

int ListLength(LinkList* L) {
	LinkList* p = L->next;
	int i = 0;
	while (p) {
		++i;
		p = p->next;
	}
	return i;
}

4. Output singly linked list 

void DispList(LinkList* L) {
	LinkList* p = L->next;
	while (p) {
		cout << p->data;
		p = p->next;
	}
}

5. Through the tail pointer, insert elements after the tail node, and insert the carry number to the back of the linked list when it is used for carry

void InsertRear(LinkList*& R, int x) {
	LinkList* newNode = new LinkList;
	newNode->data = x;
	R->next = newNode;
	newNode->next = NULL;
	R = newNode;        // 尾指针指向新建的节点
}

 6. Multiply the number by each number of the node, get and process the result, and carry at the same time

Analysis and understanding of ideas: take the factorial of 5 as an example

If the data stored in the node after the multiplication operation is less than 10, no new node is inserted at the tail node.

On the contrary, if the data saved by the node after the multiplication operation is greater than or equal to 10, a new node needs to be inserted at the end node, and the new node saves the carry number.

 Look at the code in detail

void MultList(LinkList*& L, LinkList*& R, int x) {
	LinkList* p = L->next;      // 从第一个存储数字的节点开始
	int up = 0, sum;            // 存储进位的变量up初始值为0
	while (p) {                 // 遍历当前链表,并相乘改变当前位置的值,并得到进位
		sum = p->data * x + up; // 先得到相乘并加上进位的结果
		p->data = sum % 10;     // 更新当前节点data值
		up = sum / 10;          // 更新进位数字
		p = p->next;            // 移动到下一个节点
	}

//  只有当数字乘遍所有当前节点后,进位数字仍不为0,才代表结果的位数发生了改变
//  如果此时进位仍不为0的话,将进位的数字倒序插入链表后面
	while (up) {
		InsertRear(R, up % 10);
		up /= 10;
	}
}

 7. Reverse singly linked list

Thinking analysis and understanding: here is still taking the factorial of 5 as an example

Since the output of the singly linked list L is opposite to the desired result, it is necessary to reverse the singly linked list.

Create a new linked list head node newHead, and convert the nodes in L to newHead.

  Look at the code in detail

void ReveList(LinkList*& L) {
//  创建并初始化一个新表头
	LinkList* newHead; InitList(newHead);

//  从第一个有值的节点开始操作,依次进行反转。p代表当前正在操作的节点
	LinkList* p = L->next;
	
//  当指针未到达链表尾部时,依次得到需要操作的节点地址,并采用类似头插法的方法,将需要操作的节点依次插入到新的表头
	while (p) {
		L->next = p->next;      	// 让原链表的头节点的next指针指向下下一个节点,此时p指向跳过的那个节点,即需要操作的节点
		p->next = newHead->next;    // 将需要操作的节点的next指针,指向新表头的下一个节点
		newHead->next = p;          // 让表头的next指针指向正在操作的节点
		p = L->next;                // p指向下一个需要操作的节点
	}
	
	delete L;                   // 释放头指针指向的空间
	L = newHead;                // 让头指针指向新的头节点	
}

-------------------------------------------------- ----------------------------------------------- main function

It is necessary to insert 1 first in the singly linked list L1 as the base of the multiplication operation. Note that Rear is the tail pointer!

int main() {
//  1. 创建单链表,定义尾指针,让尾指针指向表头;此链表逆序存储结果的数字
	LinkList* L1; InitList(L1);
	LinkList* Rear = L1;
	
//  2. 将数字1插入到链表后面
	InsertRear(Rear, 1);
	
//  3. 输入n
	int n; cout << "请输入你要求阶乘的数: "; cin >> n;
	cout << endl;
	
//  4. 1~n依次与单链表上的节点进行相乘、进位等
	for (int i = 1; i <= n; ++i) {
		MultList(L1, Rear, i);
	}
	
//  5. 反转单链表
	ReveList(L1);
	
//  6. 输出结果位数,以及输出结果
	cout << "该结果共有" << ListLength(L1) << "位" << endl << endl;
	
	cout << "结果为: " << endl; DispList(L1);
	
//  7. 释放单链表
	DestroyList(L1);
	
	return 0;
}

operation result

Guess you like

Origin blog.csdn.net/henry594xiaoli/article/details/123971887