我们这个世界的一个问题是,蠢人信誓旦旦,智人满腹狐疑。
——Bertrand Russell
多项式求和, 即输入两个多项式, 然后将它们合并为一个多项式, 解决多项式求和问题是链表的应用之一。
用链表的原因是, 多项式的指数可能不是连续的, 当指数最大值很高而离散度很高时, 用线性表存储会导致空间利用率很低。 于是可以使用动态开辟结点的链表来进行优化。
首先呈上老师的代码
#include <stdio.h>
#include <malloc.h>
/**
* Linked list of integers. The key is data. The key is sorted in non-descending order.
*/
typedef struct LinkNode{
int coefficient;
int exponent;
struct LinkNode *next;
} *LinkList, *NodePtr;
/**
* Initialize the list with a header.
* @return The pointer to the header.
*/
LinkList initLinkList(){
LinkList tempHeader = (LinkList)malloc(sizeof(struct LinkNode));
tempHeader->coefficient = 0;
tempHeader->exponent = 0;
tempHeader->next = NULL;
return tempHeader;
}// Of initLinkList
/**
* Print the list.
* @param paraHeader The header of the list.
*/
void printList(LinkList paraHeader){
NodePtr p = paraHeader->next;
while (p != NULL) {
printf("%d * 10^%d + ", p->coefficient, p->exponent);
p = p->next;
}// Of while
printf("\r\n");
}// Of printList
/**
* Print one node for testing.
* @param paraPtr The pointer to the node.
* @param paraChar The name of the node.
*/
void printNode(NodePtr paraPtr, char paraChar){
if (paraPtr == NULL) {
printf("NULL\r\n");
} else {
printf("The element of %c is (%d * 10^%d)\r\n", paraChar, paraPtr->coefficient, paraPtr->exponent);
}// Of while
}// Of printNode
/**
* Add an element to the tail.
* @param paraCoefficient The coefficient of the new element.
* @param paraExponent The exponent of the new element.
*/
void appendElement(LinkList paraHeader, int paraCoefficient, int paraExponent){
NodePtr p, q;
// Step 1. Construct a new node.
q = (NodePtr)malloc(sizeof(struct LinkNode));
q->coefficient = paraCoefficient;
q->exponent = paraExponent;
q->next = NULL;
// Step 2. Search to the tail.
p = paraHeader;
while (p->next != NULL) {
p = p->next;
}// Of while
// Step 3. Now add/link.
p->next = q;
}// Of appendElement
/**
* Polynomial addition.
* @param paraList1 The first list.
* @param paraList2 The second list.
*/
void add(NodePtr paraList1, NodePtr paraList2){
NodePtr p, q, r, s;
// Step 1. Search to the position.
p = paraList1->next;
printNode(p, 'p');
q = paraList2->next;
printNode(q, 'q');
r = paraList1; // Previous pointer for inserting.
printNode(r, 'r');
free(paraList2); // The second list is destroyed.
while ((p != NULL) && (q != NULL)) {
if (p->exponent < q->exponent) {
//Link the current node of the first list.
printf("case 1\r\n");
r->next = p;
r = p;
printNode(r, 'r');
p = p->next;
printNode(p, 'p');
} else if ((p->exponent > q->exponent)) {
//Link the current node of the second list.
printf("case 2\r\n");
r->next = q;
r = q;
printNode(r, 'r');
q = q->next;
printNode(q, 'q');
} else {
printf("case 3\r\n");
//Change the current node of the first list.
p->coefficient = p->coefficient + q->coefficient;
printf("The coefficient is: %d.\r\n", p->coefficient);
if (p->coefficient == 0) {
printf("case 3.1\r\n");
s = p;
p = p->next;
printNode(p, 'p');
// free(s);
} else {
printf("case 3.2\r\n");
r = p;
printNode(r, 'r');
p = p->next;
printNode(p, 'p');
}// Of if
s = q;
q = q->next;
//printf("q is pointing to (%d, %d)\r\n", q->coefficient, q->exponent);
free(s);
}// Of if
printf("p = %ld, q = %ld \r\n", p, q);
} // Of while
printf("End of while.\r\n");
if (p == NULL) {
r->next = q;
} else {
r->next = p;
} // Of if
printf("Addition ends.\r\n");
}// Of add
/**
* Unit test 1.
*/
void additionTest1(){
// Step 1. Initialize the first polynomial.
LinkList tempList1 = initLinkList();
appendElement(tempList1, 7, 0);
appendElement(tempList1, 3, 1);
appendElement(tempList1, 9, 8);
appendElement(tempList1, 5, 17);
printList(tempList1);
// Step 2. Initialize the second polynomial.
LinkList tempList2 = initLinkList();
appendElement(tempList2, 8, 1);
appendElement(tempList2, 22, 7);
appendElement(tempList2, -9, 8);
printList(tempList2);
// Step 3. Add them to the first.
add(tempList1, tempList2);
printf("The result is: ");
printList(tempList1);
printf("\r\n");
}// Of additionTest1
/**
* Unit test 2.
*/
void additionTest2(){
// Step 1. Initialize the first polynomial.
LinkList tempList1 = initLinkList();
appendElement(tempList1, 7, 0);
appendElement(tempList1, 3, 1);
appendElement(tempList1, 9, 8);
appendElement(tempList1, 5, 17);
printList(tempList1);
// Step 2. Initialize the second polynomial.
LinkList tempList2 = initLinkList();
appendElement(tempList2, 8, 1);
appendElement(tempList2, 22, 7);
appendElement(tempList2, -9, 10);
printList(tempList2);
// Step 3. Add them to the first.
add(tempList1, tempList2);
printf("The result is: ");
printList(tempList1);
printf("\r\n");
}// Of additionTest2
/**
* The entrance.
*/
int main(){
additionTest1();
additionTest2();
printf("Finish.\r\n");
return 0;
}// Of main
单链表定义
#include <iostream>
#include <vector>
#define remilia int
#define isMyWife main
using namespace std;
template<class ElemType>
class LinkedList {
private:
class Node {
private:
ElemType data;
Node* next;
public:
virtual ~Node() {
}
Node();
Node(ElemType data, Node* next) {
this -> data = data;
this -> next = next;
}
ElemType getData() {
return this -> data;
}
void setData(ElemType elem) {
this -> data = elem;
}
Node* getNext() {
return this -> next;
}
void setNext(Node* node) {
this -> next = node;
}
};
int length;
Node* head;
Node* tail;
// 引入迭代器
Node* iterator;
public:
virtual ~LinkedList();
LinkedList();
LinkedList(vector<ElemType> v);
Node* initIterator() {
return (this -> iterator = this -> head);
}
// get the length of linkedlist
int getLength();
// print all of the linkedlist
void outputList();
/**
* @brief append a node to the tail
* @return the result of appending 1 -> success
* @param elem
* the appending is always successful
**/
bool pushBack(ElemType elem);
/**
* @brief append a node to the head
* @param elem
* @return the result of appending 1 -> success
* the appending is always successful
**/
bool pushHead(ElemType elem);
/**
* @brief delete a node from head
* @return the result of deleting 1 -> success, 0 -> failute
* the reason of failure is that the head node isn't existed
**/
bool popHead();
/**
* @brief delete a node from tail
* @return the result of deleting 1 -> success, 0 -> failute
* the reason of failure is that the tail node isn't existed
* @return
**/
bool popBack();
// insert an element to the given position
bool insertElement(int paraPosition, ElemType elem);
/**
* @brief delete a node by the paraPosition
* @param the position of the node needed deleted
* @return 1 -> success, 0 -> fail
* the reason of failure is the position out of range
**/
bool deleteElementByParaPosition(int paraPosition);
/**
* @brief clear the list
*
**/
void clear();
/**
* @brief get a element by paraPosition
*
*
* @return the element
**/
ElemType getElement(int paraPosition);
};
template<class ElemType>
LinkedList<ElemType>::~LinkedList() {
}
template<class ElemType>
LinkedList<ElemType>::LinkedList() {
this -> length = 0;
this -> head = this -> tail = nullptr;
}
template<class ElemType>
LinkedList<ElemType>::LinkedList(vector<ElemType> v) {
for (auto e : v) {
this -> pushBack(e);
}
}
template<class ElemType>
bool LinkedList<ElemType>::pushBack(ElemType elem) {
// if the tail equals null, the head equals null too
if (this -> tail == nullptr) {
this -> head = this -> tail = new Node(elem, nullptr);
} else {
Node* newTail = new Node(elem, nullptr);
this -> tail -> setNext(newTail);
this -> tail = newTail;
}
this -> length++;
return 1;
}
template<class ElemType>
bool LinkedList<ElemType>::pushHead(ElemType elem) {
if (this -> head == nullptr) {
this -> head = this -> tail = new Node(elem, nullptr);
} else {
Node* newTail = new Node(elem, head);
this -> head = newTail;
}
this -> length++;
return 1;
}
template<class ElemType>
bool LinkedList<ElemType>::popHead() {
if (this -> length == 1) {
this -> head = this -> tail = nullptr;
}
if (this -> head == nullptr) {
return 0;
} else {
Node* temp = this -> head;
this -> head = this -> head -> getNext();
delete temp;
return 1;
}
}
template<class ElemType>
bool LinkedList<ElemType>::popBack() {
if (this -> length == 1) {
this -> head = this -> tail = nullptr;
}
if (this -> tail == nullptr) {
return 0;
} else {
Node* temp = this -> head;
while (temp -> getNext() != this -> tail) {
temp = temp -> getNext();
}
delete temp -> getNext();
this -> tail = temp;
return 1;
}
}
template<class ElemType>
void LinkedList<ElemType>::outputList() {
Node* temp = this -> head;
while (temp != nullptr) {
cout << temp -> getData() << " ";
temp = temp -> getNext();
}
putchar('\n');
}
template<class ElemType>
int LinkedList<ElemType>::getLength() {
return this -> length;
}
template<class ElemType>
void LinkedList<ElemType>::clear() {
Node* temp = this -> head;
Node* storge = temp;
while (temp != nullptr) {
temp = temp -> getNext();
delete storge;
storge = temp;
}
delete storge;
this -> head = this -> tail = nullptr;
this -> length = 0;
}
template<class ElemType>
bool LinkedList<ElemType>::deleteElementByParaPosition(int paraPosition) {
if (paraPosition > this -> getLength()) {
return 0;
}
if (paraPosition == 1) {
return popHead();
}
int recordIndex = 1;
Node* temp = this -> head;
while (recordIndex < paraPosition - 1) {
temp = temp -> getNext();
recordIndex++;
}
Node* recorder = temp -> getNext();
temp -> setNext(recorder -> getNext());
delete recorder;
return 1;
}
template<class ElemType>
bool LinkedList<ElemType>::insertElement(int paraPosition, ElemType elem) {
if (paraPosition > this -> getLength() + 1) {
return 0;
}
if (paraPosition == 1) {
return this -> pushHead(elem);
}
Node* temp = this -> head;
int recordIndex = 1;
while (recordIndex < paraPosition - 1) {
temp = temp -> getNext();
recordIndex++;
}
Node* newNode = new Node(elem, temp -> getNext());
temp -> setNext(newNode);
this -> length++;
return 1;
}
template<class ElemType>
ElemType LinkedList<ElemType>::getElement(int paraPosition) {
if (paraPosition > this -> length) {
throw "out of range...";
}
int recordIndex = 1;
Node* temp = this -> head;
while (recordIndex < paraPosition) {
temp = temp -> getNext();
recordIndex++;
}
return temp -> getData();
}
remilia isMyWife() {
return 0;
}
重载pair的输出运算符
// 重载pair的输出运算符
template<class T, class U>
std::ostream& operator<<(std::ostream& os, const std::pair<T, U>& p) {
os << p.first << "x^" << p.second << " ";
return os;
}
求和函数
// 参数使用pair
// pair<系数, 指数>
LinkedList<pair<int, int>> add(LinkedList<pair<int, int>>& a, LinkedList<pair<int, int>>& b) {
// Node是内部私有类, 因此这里使用自动类型进行推断
LinkedList<pair<int, int>> ans;
auto iteratorA = a.initIterator();
auto iteratorB = b.initIterator();
while (iteratorA && iteratorB) {
if (iteratorA -> getData().second < iteratorB -> getData().second) {
ans.pushBack({iteratorA -> getData().first, iteratorA -> getData().second});
iteratorA = iteratorA -> getNext();
} else if (iteratorA -> getData().second > iteratorB -> getData().second) {
ans.pushBack({iteratorB -> getData().first, iteratorB -> getData().second});
iteratorB = iteratorB -> getNext();
} else {
int sum = iteratorA -> getData().second + iteratorB -> getData().second;
if (sum) {
ans.pushBack({sum, iteratorA -> getData().second});
}
iteratorA = iteratorA -> getNext();
iteratorB = iteratorB -> getNext();
}
}
while (iteratorA) {
ans.pushBack({iteratorA -> getData().first, iteratorA -> getData().second});
iteratorA = iteratorA -> getNext();
}
while (iteratorB) {
ans.pushBack({iteratorB -> getData().first, iteratorB -> getData().second});
iteratorB = iteratorB -> getNext();
}
a.clear();
b.clear();
return ans;
}
总体代码
#include <bits/stdc++.h>
#define remilia int
#define isMyWife main
using namespace std;
// 重载pair的输出运算符
template<class T, class U>
std::ostream& operator<<(std::ostream& os, const std::pair<T, U>& p) {
os << p.first << "x^" << p.second << " ";
return os;
}
template<class ElemType>
class LinkedList {
private:
class Node {
private:
ElemType data;
Node* next;
public:
virtual ~Node() {
}
Node();
Node(ElemType data, Node* next) {
this -> data = data;
this -> next = next;
}
ElemType getData() {
return this -> data;
}
void setData(ElemType elem) {
this -> data = elem;
}
Node* getNext() {
return this -> next;
}
void setNext(Node* node) {
this -> next = node;
}
};
int length;
Node* head;
Node* tail;
public:
virtual ~LinkedList();
LinkedList();
LinkedList(vector<ElemType> v);
// 引入迭代器
Node* iterator;
Node* initIterator() {
return (this -> iterator = this -> head);
}
// get the length of linkedlist
int getLength();
// print all of the linkedlist
void outputList();
/**
* @brief append a node to the tail
* @return the result of appending 1 -> success
* @param elem
* the appending is always successful
**/
bool pushBack(ElemType elem);
/**
* @brief append a node to the head
* @param elem
* @return the result of appending 1 -> success
* the appending is always successful
**/
bool pushHead(ElemType elem);
/**
* @brief delete a node from head
* @return the result of deleting 1 -> success, 0 -> failute
* the reason of failure is that the head node isn't existed
**/
bool popHead();
/**
* @brief delete a node from tail
* @return the result of deleting 1 -> success, 0 -> failute
* the reason of failure is that the tail node isn't existed
* @return
**/
bool popBack();
// insert an element to the given position
bool insertElement(int paraPosition, ElemType elem);
/**
* @brief delete a node by the paraPosition
* @param the position of the node needed deleted
* @return 1 -> success, 0 -> fail
* the reason of failure is the position out of range
**/
bool deleteElementByParaPosition(int paraPosition);
/**
* @brief clear the list
*
**/
void clear();
/**
* @brief get a element by paraPosition
*
*
* @return the element
**/
ElemType getElement(int paraPosition);
};
template<class ElemType>
LinkedList<ElemType>::~LinkedList() {
}
template<class ElemType>
LinkedList<ElemType>::LinkedList() {
this -> length = 0;
this -> head = this -> tail = nullptr;
}
template<class ElemType>
LinkedList<ElemType>::LinkedList(vector<ElemType> v) {
for (auto e : v) {
this -> pushBack(e);
}
}
template<class ElemType>
bool LinkedList<ElemType>::pushBack(ElemType elem) {
// if the tail equals null, the head equals null too
if (this -> tail == nullptr) {
this -> head = this -> tail = new Node(elem, nullptr);
} else {
Node* newTail = new Node(elem, nullptr);
this -> tail -> setNext(newTail);
this -> tail = newTail;
}
this -> length++;
return 1;
}
template<class ElemType>
bool LinkedList<ElemType>::pushHead(ElemType elem) {
if (this -> head == nullptr) {
this -> head = this -> tail = new Node(elem, nullptr);
} else {
Node* newTail = new Node(elem, head);
this -> head = newTail;
}
this -> length++;
return 1;
}
template<class ElemType>
bool LinkedList<ElemType>::popHead() {
if (this -> length == 1) {
this -> head = this -> tail = nullptr;
}
if (this -> head == nullptr) {
return 0;
} else {
Node* temp = this -> head;
this -> head = this -> head -> getNext();
delete temp;
return 1;
}
}
template<class ElemType>
bool LinkedList<ElemType>::popBack() {
if (this -> length == 1) {
this -> head = this -> tail = nullptr;
}
if (this -> tail == nullptr) {
return 0;
} else {
Node* temp = this -> head;
while (temp -> getNext() != this -> tail) {
temp = temp -> getNext();
}
delete temp -> getNext();
this -> tail = temp;
return 1;
}
}
template<class ElemType>
void LinkedList<ElemType>::outputList() {
Node* temp = this -> head;
while (temp != nullptr) {
cout << temp -> getData() << " ";
temp = temp -> getNext();
}
putchar('\n');
}
template<class ElemType>
int LinkedList<ElemType>::getLength() {
return this -> length;
}
template<class ElemType>
void LinkedList<ElemType>::clear() {
Node* temp = this -> head;
Node* storge = temp;
while (temp != nullptr) {
temp = temp -> getNext();
delete storge;
storge = temp;
}
delete storge;
this -> head = this -> tail = nullptr;
this -> length = 0;
}
template<class ElemType>
bool LinkedList<ElemType>::deleteElementByParaPosition(int paraPosition) {
if (paraPosition > this -> getLength()) {
return 0;
}
if (paraPosition == 1) {
return popHead();
}
int recordIndex = 1;
Node* temp = this -> head;
while (recordIndex < paraPosition - 1) {
temp = temp -> getNext();
recordIndex++;
}
Node* recorder = temp -> getNext();
temp -> setNext(recorder -> getNext());
delete recorder;
return 1;
}
template<class ElemType>
bool LinkedList<ElemType>::insertElement(int paraPosition, ElemType elem) {
if (paraPosition > this -> getLength() + 1) {
return 0;
}
if (paraPosition == 1) {
return this -> pushHead(elem);
}
Node* temp = this -> head;
int recordIndex = 1;
while (recordIndex < paraPosition - 1) {
temp = temp -> getNext();
recordIndex++;
}
Node* newNode = new Node(elem, temp -> getNext());
temp -> setNext(newNode);
this -> length++;
return 1;
}
template<class ElemType>
ElemType LinkedList<ElemType>::getElement(int paraPosition) {
if (paraPosition > this -> length) {
throw "out of range...";
}
int recordIndex = 1;
Node* temp = this -> head;
while (recordIndex < paraPosition) {
temp = temp -> getNext();
recordIndex++;
}
return temp -> getData();
}
// 参数使用pair
// pair<系数, 指数>
LinkedList<pair<int, int>> add(LinkedList<pair<int, int>>& a, LinkedList<pair<int, int>>& b) {
// Node是内部私有类, 因此这里使用自动类型进行推断
LinkedList<pair<int, int>> ans;
auto iteratorA = a.initIterator();
auto iteratorB = b.initIterator();
while (iteratorA && iteratorB) {
if (iteratorA -> getData().second < iteratorB -> getData().second) {
ans.pushBack({iteratorA -> getData().first, iteratorA -> getData().second});
iteratorA = iteratorA -> getNext();
} else if (iteratorA -> getData().second > iteratorB -> getData().second) {
ans.pushBack({iteratorB -> getData().first, iteratorB -> getData().second});
iteratorB = iteratorB -> getNext();
} else {
int sum = iteratorA -> getData().second + iteratorB -> getData().second;
if (sum) {
ans.pushBack({sum, iteratorA -> getData().second});
}
iteratorA = iteratorA -> getNext();
iteratorB = iteratorB -> getNext();
}
}
while (iteratorA) {
ans.pushBack({iteratorA -> getData().first, iteratorA -> getData().second});
iteratorA = iteratorA -> getNext();
}
while (iteratorB) {
ans.pushBack({iteratorB -> getData().first, iteratorB -> getData().second});
iteratorB = iteratorB -> getNext();
}
a.clear();
b.clear();
return ans;
}
remilia isMyWife() {
srand(time(NULL));
LinkedList<pair<int, int>> a, b, c;
for (int i = 1; i <= 10; i++) {
a.pushBack({i, i});
}
for (int j = 10; j <= 20; j++) {
b.pushBack({j, j});
}
c = add(a, b);
c.outputList();
return 0;
}