# Course practice experiment 5: implementation and application of linear table

## Problem description and requirements

(1) Implement the sequence table class and basic operations and test them.

(2) Realize the single linked list class and basic operation and test it. In addition to the basic operations, add inversion, search by value, statistics by value, deletion and other (recursive and non recursive) algorithms for the single linked list class and test them.

(3) Design and implement the ordered single linked list class, and add algorithms such as value insertion and ordered table merging under the ordered table.

(4) Use the single linked list to complete the simple management of daily expenditure.

Enter n expense items (you can choose to import from file), and output all expense items in turn.

Find the minimum, maximum and average consumption of these n expenditure items.

Find out all the expenses of a day by date.

Find out the cost of the project by date and project.

Find out all the expenses of the project according to the project. For example, ask for a total amount of money spent on shoes.

## Outline design

(1) Understanding and secondary generalization of the experimental content

Use the definition of linear list and linked list to realize the basic operation, and realize the daily expenditure management by defining the data structure of nodes.

(2) Give the function list of the system

Basic operations of sequence table class: increase, decrease, clear, etc

Basic operation of single linked list

Inverse of single linked list, search by value, statistics by value, deletion, etc

Algorithms such as inserting by value and merging ordered tables under ordered tables

Simple management of daily expenses

(3) Interface design of program operation (it can be illustrated, for example: the screen prompt appears first, and the user is asked to select the mode of input configuration, 1 input the live unit coordinates from the keyboard, 2... 3... And then the user)

(4) Determine the overall design idea, which data structure to adopt, which classes to design, the functions of various classes, the introduction of class methods, and the description of the relationship between classes

Using the data structure of sequence table and single linked table, a sequence table class and a single linked table class are designed, and then a single linked table class is designed for the simple management of daily expenditure. Each class has basic operation methods: size, empty, clear, full, reverse, retrieve, replace, remove and insert

## detailed design

Inverse of single linked list: void reverse();

Starting from the head node, make the pointer p point to the head node, then make the next of the first head node point to the third node, and the next of the second node point to the head node, so as to complete the sequential exchange of the first two nodes, and then make the head point to the second node to continue the cycle and exchange in turn.

Search by value of single linked list: error_ code list<list_ entry>::search(const list_ entry&x, int &position)

Start from the head node of the single linked list, and then use position to record the position. If the value of a node is equal to the searched value, the searched position will be recorded.

Attached code:

#include <iostream> #include <ctime> #include <random> #include <algorithm> using namespace std; enum Error_code { success, fail, rangeerror, overflow, underflow, range_over }; int max_list = 10000; template <class List_entry> class List { public: List() { count = 0; }//Constructor int size() const; bool full() const; bool empty() const; void traverse(void(*visit)(List_entry&)); Error_code retrieve(int position, List_entry& x) const; Error_code remove(int position, List_entry& x); Error_code insert(int position, const List_entry& x); void printout() { for (int i = 0; i < count; i++) { cout << entry[i] << " "; } cout << endl; } void ListSort()//Sequential table sort { for (int i = 0; i < count - 1; ++i) { int flag = 0; for (int j = 0; j < count - i - 1; ++j) { if (entry[j]>entry[j + 1]) { swap(entry[j], entry[j + 1]); flag = 1; } } if (flag == 0) break; } } protected: //Private member data int count; List_entry entry[10000];//The so-called contiguous means that it is stored in an array }; template <class List_entry> int List <List_entry>::size() const { return count; } template <class List_entry> bool List <List_entry>::full() const { if (count == max_list) return true; else return false; } template <class List_entry> bool List <List_entry>::empty() const { if (count == 0) return true; else return false; } template <class List_entry> Error_code List<List_entry>::insert(int position, const List_entry& x) { if (full()) return overflow;//overflow if (position<0 || position>count) return range_over; //Insertion point error for (int i = count - 1; i >= position; i--) entry[i + 1] = entry[i]; //Move element (back to front) entry[position] = x; //Put element count++; //Increase the number of Statistics return success; } template <class List_entry> Error_code List<List_entry> ::remove(int position, List_entry &x) { if (count == 0) return underflow; if (position < 0 || position >= count) return rangeerror; x = entry[position]; count--; while (position < count - 1) { entry[position] = entry[position + 1]; position++; } return success; } template <class List_entry> Error_code List<List_entry> ::retrieve(int position, List_entry &x) const //If the position value is illegal, an error message is returned. Otherwise, the position element in the table is obtained according to the position value and returned by x. { if (position < 0 || position >= count) return rangeerror; x = entry[position]; return success; } template <class List_entry> void List<List_entry>::traverse(void(*visit)(List_entry&)) { for (int i = 0; i<count; i++) (*visit)(entry[i]); //Here, the visit function represents the specific actions performed on each table element during the specified traversal } Error_code sequential_search(int x, List<int> a, int &count) { for (int i = 0; i < a.size(); i++) { int m; a.retrieve(i, m); count++; if (m == x) { return success; } } count -= a.size(); return fail; } Error_code binary_search_nonrecursive(const int &target, const List<int> &x) { int data; int bottom = 0, top = x.size() - 1; while (bottom < top) { int mid = (bottom + top) / 2; x.retrieve(mid, data); if (target > data) bottom = mid + 1; else top = mid; } if (top < bottom) return fail; else { x.retrieve(bottom, data); if (data == target) return success; else return fail; } } Error_code binary_search_recursive(const List<int> &x, const int &target, int bottom, int top) { { int data; if (bottom < top) { // List has more than one entry. int mid = (bottom + top) / 2; x.retrieve(mid, data); if (data < target) // Reduce to top half of list. return binary_search_recursive(x, target, mid + 1, top); else // Reduce to bottom half of list. return binary_search_recursive(x, target, bottom, mid); } else if (top < bottom) return fail; // List is empty. else { // List has exactly one entry. x.retrieve(bottom, data); if (data == target) return success; else return fail; } } } int main() { List<int> unordered_list; int n; cout << "Please enter the number of integers stored in the linear table(1~9999):"; cin >> n; for (int i = 0; i < n; i++) { int x=rand()%10000; unordered_list.insert(i, x); } cout << "Unordered table generated:"; unordered_list.printout(); int m; cout << "Please enter the number of duplicate searches:"; cin >> m; Error_code result; int count_success=0, count_fail=0, count_compare=0; clock_t start_t, end_t; double suc_t=0, fail_t=0; for (int i = 0; i < m; i++) { start_t = clock(); result = sequential_search(rand()%10000, unordered_list, count_compare); if (result == 0) { end_t = clock(); suc_t += (double)(end_t - start_t) / CLOCKS_PER_SEC; count_success++; } if (result == 1) { end_t = clock(); fail_t += (double)(end_t - start_t) / CLOCKS_PER_SEC; count_fail++; } } cout << endl; cout << "Find sequentially in an unordered table:" << endl; cout << "When the search is successful, the absolute execution time of the algorithm is" << suc_t / count_success*m << "s" << endl; cout << "When the search fails, the absolute execution time of the algorithm is" << fail_t / count_fail*m << "s" << endl; cout << "When the search is successful, the average number of keyword comparisons is" << count_compare / count_success << endl; cout << endl; unordered_list.ListSort(); cout << "After sorting, the generated ordered table is:"; unordered_list.printout(); cout << endl; count_success = 0, count_fail = 0, count_compare = 0; suc_t = 0, fail_t = 0; for (int i = 0; i < m; i++) { start_t = clock(); result = sequential_search(rand() % 10000, unordered_list, count_compare); if (result == 0) { end_t = clock(); suc_t += (double)(end_t - start_t) / CLOCKS_PER_SEC; count_success++; } else if (result == 1) { end_t = clock(); fail_t += (double)(end_t - start_t) / CLOCKS_PER_SEC; count_fail++; } } cout << "Find sequentially in an ordered table:" << endl; cout << "When the search is successful, the absolute execution time of the algorithm is" << suc_t / count_success*m << "s" << endl; cout << "When the search fails, the absolute execution time of the algorithm is" << fail_t / count_fail*m << "s" << endl; cout << "When the search is successful, the average number of keyword comparisons is" << count_compare / count_success << endl; cout << endl; suc_t = 0, fail_t = 0; for (int i = 0; i < m; i++) { start_t = clock(); result = binary_search_nonrecursive(rand() % 10000, unordered_list); if (result == 0) { end_t = clock(); suc_t += (double)(end_t - start_t) / CLOCKS_PER_SEC; count_success++; } else if (result == 1) { end_t = clock(); fail_t += (double)(end_t - start_t) / CLOCKS_PER_SEC; count_fail++; } } cout << "Using non recursive binary lookup in ordered tables:" << endl; cout << "When the search is successful, the absolute execution time of the algorithm is" << suc_t / count_success*m << "s" << endl; cout << "When the search fails, the absolute execution time of the algorithm is" << fail_t / count_fail*m << "s" << endl; cout << endl; suc_t = 0, fail_t = 0; for (int i = 0; i < m; i++) { start_t = clock(); result = binary_search_recursive(unordered_list, rand() % 10000, 0, unordered_list.size()-1); if (result == 0) { end_t = clock(); suc_t += (double)(end_t - start_t) / CLOCKS_PER_SEC; count_success++; } else if (result == 1) { end_t = clock(); fail_t += (double)(end_t - start_t) / CLOCKS_PER_SEC; count_fail++; } } cout << "Using recursive binary lookup in ordered tables:" << endl; cout << "When the search is successful, the absolute execution time of the algorithm is" << suc_t / count_success*m << "s" << endl; cout << "When the search fails, the absolute execution time of the algorithm is" << fail_t / count_fail*m << "s" << endl; cout << endl; system("pause"); }

## experimental result

Design and provide corresponding test methods and results according to the requirements of the subject. Specific test cases can be given, and each test case can generally be listed:

Test input: None

Test purpose: check whether the basic function is wrong

Actual output:

Test conclusion: passed

## Experimental analysis and discussion

The main problems encountered in the experiment are how to correctly return the error code in the process of realizing the basic functions, how to improve the program, how to correctly define the data structure of the node and how to respond when applying the basic functions of sequence list and linked list.