Data structure training report (linear table + stack and queue + binary tree + graph + sorting)

The first blog from the draft box.

1, Basic operation of linear table

1. Experimental contents:

(1) Input and establish polynomials, and store polynomials in a single linked list with header nodes.
(2) Output polynomial in the form of integer sequence: n, c1, e1, c2, e2... cn, en, where n is the number of terms of the polynomial, ci and ei are the coefficients and exponents of the i-th term respectively. The sequence is arranged in exponential descending order.
(3) Add polynomials a and b, establish polynomials a and b, and output the added polynomials.
(4) Polynomials a and b are subtracted, polynomials a and b are established, and the subtracted polynomials are output.
(5) Add polynomials a and b, establish polynomials a and b, and output the multiplied polynomials.

2. Design idea:

We can decompose the experimental content into several questions: if we store polynomials? How to complete the operation of polynomials? Next, refine these questions.
1. Polynomial storage: the experimental content has prompted the use of linked list storage. The linked list storage content has two points: one is the data field, the other is the pointer field; The data field has two parts: one is coefficient, the other is index; The pointer field indicates the next node pointed to, which completes the storage of polynomials.
2. Polynomial output: essentially, it is the traversal of the linked list. After entering from the entry, each element is accessed in turn. Here we should pay attention to the particularity of polynomials, so we should discuss them by classification. If the index and coefficient of a term exist, they can be output directly. Pay attention to using x of second square Power of x The power connection of x (of course not); If the index is 0, it means that this term is a constant term, so you don't need to output the following x of second square Power of x The power sum coefficient of x; If the coefficient is 0, skip this item directly, because this item is useless and can be directly omitted in the calculation process. Another small beautification is that if it is not the last item, it will output "+" to connect the two items.
3. Addition and subtraction of Polynomials: the principle of addition and subtraction is very simple, that is, the terms with the same exponent are combined (added or subtracted) and finally output. The design idea is to set two pointers to two polynomials respectively. Here, the polynomials are stored in a linked list. Since the contents are required to be arranged in exponential descending order, we don't need to compare the size. We can directly traverse from front to back. When traversing, we compare whether the indexes of the two pointers are the same. If they are the same, the old ones are merged, otherwise the large ones will be added to the result linked list every time, And move the pointer back until one of the two linked lists is null. Finally, connect the remaining items to the result linked list.
4. Polynomial multiplication: since the storage of polynomials is arranged in exponential descending order, the exponential multiplication of the first element of the two polynomials must be the largest. We can calculate this first. Then, the two-layer for loop enumerates the results of the multiplication of the two items, and considers where the generated new item is inserted: either forward or backward.

3. Experiment code:

typedef struct LIST///Structure 
{
    int exp;///Index
    double coef;///Coefficient
    struct LIST* next;
} LIST,*LISTLINK;//Linked list 
LISTLINK A,B,C;///Three polynomials 
LISTLINK taila,tailb,tailc;///Tail pointer 
int cnta,cntb;
int n,m;///Number of terms of two polynomials 
void initlist(LISTLINK &L,LISTLINK &tail)//Initialize linked list 
{
    L=(LIST*)malloc(sizeof(LIST));
    L->next=NULL;
    tail=L;
}
void Insertlist(int exp,double coef,LISTLINK &L,LISTLINK &tail) 
{///Insert element  
    LIST* tmp=(LIST*)malloc(sizeof(LIST));///Application space 
    tmp->coef=coef;//assignment 
    tmp->exp=exp;
    tmp->next=NULL;
    tail->next=tmp;
    tail=tmp;
}
void output(LISTLINK &L,LISTLINK &tail)
{///Traverse the linked list and pay attention to the output format 
    LISTLINK p=L->next;
    bool flag=0;
    while(p)
    {
    	if(p->coef!=0&&p->exp!=0)///When the index and coefficient are not 0, the output index and coefficient and regulate the output of x 
        	printf("%.2fx^%d",p->coef,p->exp),flag=1;
        else if(p->exp==0) printf("%.2f",p->coef),flag=1;//When the index is 0, it means that only the output coefficient is required, and x is not output 
        if(p->next!=NULL) cout<<"+";///If it is not the last item, output it+ 
        p=p->next;
    }
    if(!flag) cout<<"0";///flag is 0, indicating that it is an empty linked list and outputs 0 
}
void add()
{//Polynomials can be added with the same coefficients directly by exponential addition 
    LIST* pa=A->next;
    LIST* pb=B->next;
    while(pa&&pb)
    {///When there are elements in both tables, compare the size of the index and insert the large one into the linked list each time 
        if(pa->exp>pb->exp)
        {
            Insertlist(pa->exp,pa->coef,C,tailc);
            pa=pa->next;
        }
        else if(pa->exp<pb->exp)
        {
            Insertlist(pb->exp,pb->coef,C,tailc);
            pb=pb->next;
        }
        else
        {//When the index is the same, the coefficient shall be combined 
            double x=pa->coef+pb->coef;
            if(x!=0) Insertlist(pa->exp,x,C,tailc);
            pa=pa->next;
            pb=pb->next;
        }
    }
    ///Join the remaining elements into the table 
    while(pa)
    {
        Insertlist(pa->exp,pa->coef,C,tailc);
        pa=pa->next;
    }
    while(pb)
    {
        Insertlist(pb->exp,pb->coef,C,tailc);
        pb=pb->next;
    }
    output(C,tailc);///Output results
    puts("");
}
void sub()
{//Polynomial subtraction, the same coefficient can be directly exponentially subtracted 
    LIST* pa=A->next;
    LIST* pb=B->next;
    while(pa&&pb)
    {///When both tables have elements, the large one is inserted into the table 
        if(pa->exp>pb->exp)
        {
            Insertlist(pa->exp,pa->coef,C,tailc);
            pa=pa->next;
        }
        else if(pa->exp<pb->exp)
        {
            Insertlist(pb->exp,pb->coef,C,tailc);
            pb=pb->next;
        }
        else
        {//Merge when the index is the same 
            double x=pa->coef-pb->coef;
            if(x!=0) Insertlist(pa->exp,x,C,tailc);
            pa=pa->next;
            pb=pb->next;
        }
    }
    ///Connect the remaining elements to the table 
    while(pa)
    {
        Insertlist(pa->exp,pa->coef,C,tailc);
        pa=pa->next;
    }
    while(pb)
    {
        Insertlist(pb->exp,pb->coef,C,tailc);
        pb=pb->next;
    }
    output(C,tailc);///Output results
    puts("");
}
LISTLINK mul()///Polynomial multiplication 
{
/**
Basic principle: since the storage of polynomials is arranged in exponential descending order, the exponential multiplication of the first element in the two polynomials must be the largest, 
We can calculate this first.
Then, the two-layer for loop enumerates the results of the multiplication of the two items, and considers where the generated new item is inserted: either forward or backward 
*/
	int n=1;//Number of items 
    LISTLINK p1;
    LISTLINK p2;
    LISTLINK p=(LIST*)malloc(sizeof(LIST));
    LISTLINK pre=(LIST*)malloc(sizeof(LIST));
    LISTLINK phead=(LIST*)malloc(sizeof(LIST));
	p1=A->next,p2=B->next;
	//LISTLINK p,pre,phead;/// Working pointer the previous header node of the working pointer
	p->coef=p1->coef*p2->coef;
	p->exp=p1->exp+p2->exp;///This must be the one with the largest index
	p->next=NULL;
	phead->next=p;
	pre->next=p;
	///Two layer for loop traversal
	while(p1){
		p2=B->next;///Note that the value of p2 should be reset every time 
		while(p2){
			p=phead->next;//Record the head node of the result linked list 
			LISTLINK pnew=(LIST*)malloc(sizeof(LIST));
			pnew->coef=p1->coef*p2->coef;///Coefficient multiplication 
			pnew->exp=p1->exp+p2->exp;//Exponential addition 
			pnew->next=NULL; 
			if(pnew->coef==0) continue;///Skip directly when the coefficient is 0
			for(int i=0;i<n*m;i++){///Maximum n*m items 
				if(p->exp==pnew->exp){///Standard addition 
					if(n==1) break;///The first item has been calculated 
					else{//merge 
						p->coef=p->coef+pnew->coef;
						n++;///Number of items + 1 
						break;///Jump out of loop 
					}
				}
				else if(p->exp>pnew->exp){///Insert backward 
					pre=p;//Update the previous pointer of the work node 
					if(p->next==NULL){
						p->next=pnew;
						n++;
						break;
					}
					else p=p->next;
				} 
				else{///Insert forward 
					pre->next=pnew; 
					pnew->next=p;
					pre=pnew;
					n++;
					break;
				}
			} 
			p2=p2->next;///p2 movement 
		}
		p1=p1->next;//p1 movement 
	} 
	return phead;
	
}
int main()
{
	cout<<"Please enter the number of terms of two polynomials"<<endl; 
    n=read(),m=read();///Number of terms of polynomial A number of terms of polynomial B
///Initialize three linked lists from large to small index 
    initlist(A,taila);
    initlist(B,tailb);
    cout<<"Please enter the term of the first polynomial:Coefficient, index (input in descending order of index)"<<endl;
    for(int i=1; i<=n; i++)
    {
        double coef;
        cin>>coef;
        int exp=read();
        Insertlist(exp,coef,A,taila);///Insert element 

    }
    cout<<"Please enter the term of the second polynomial:Coefficient, index (input in descending order of index)"<<endl;
    for(int i=1; i<=m; i++)
    {
        double coef;
        cin>>coef;
        int exp=read();
        Insertlist(exp,coef,B,tailb);///Insert element 
    }
    cout<<"The first polynomial is:\n";
	output(A,taila);puts("");
	cout<<"The second polynomial is:\n";
	output(B,tailb);puts("");
    initlist(C,tailc);
    cout<<"The result of adding two polynomials is:\n";
    add();
    initlist(C,tailc);
    cout<<"The result of subtracting two polynomials is:\n";
    sub();
    initlist(C,tailc);
    cout<<"The result of multiplying two polynomials is:\n";
    C=mul();
    output(C,tailc);
    return 0;
}

2, Basic operation of stack and queue

1. Experimental contents:

1. Experimental purpose:
(1) Master the implementation of sequence stack and chain queue;
(2) Can use the basic operation of stack and queue to solve practical problems;
2. Experimental requirements: the parking lot is a long and narrow passage that can park n cars, and there is only one gate for access (stack structure). The cars are arranged in the parking lot according to the order of arrival. If the parking lot is full of cars, the later cars can only wait on the lane change outside the door. Once a car drives away in the parking lot, the first car on the sidewalk can enter (queue structure). Each car parked in the parking lot shall pay the fee according to its length of stay in the parking lot when leaving (here, it is assumed that the car cannot drive directly from the waiting sidewalk outside the door). Try to design a program to realize parking lot management, and simulate management according to the data sequence input from the terminal.
(1) It is realized by sequential stack and chain queue;
(2) Each set of input data includes three data items: vehicle license plate, arrival or departure mark and time.; (3) The output information after operating each set of input data is: vehicle arrival: output the parking position of the vehicle in the parking lot or on the sidewalk; vehicle departure: output the dwell time and cost (no charge for waiting on the sidewalk)

2. Design idea:

Stack and queue problems combined with real life.
Firstly, according to the experimental requirements, we can abstract the parking lot as a stack and the lane change as a queue. Every time a new car comes, you should judge whether to arrive or leave. If you arrive, when the parking lot is full, you can only stay on the lane change and put it in the queue; Otherwise, you can drive the car directly to the parking lot and put it in the stack. If it is to leave, it should be noted that the car must be the latest one in the stack. At the same time, we should also consider the impact of the car after driving away: if the parking space was originally full, the car on the lane will enter the parking lot after leaving until the parking lot is full.
As for the cost calculation, it should be noted that there is no charge for waiting on the lane change, so when the car enters the parking lot from the lane change, the arrival time should be updated to facilitate the cost calculation when leaving. Combined with the actual situation, it is also added to modify the parking lot capacity and parking unit hour cost. After setting the parking unit hour cost as a global variable, the latter is a very easy thing. For the former, the changes of parking lot and lane changing vehicles after capacity expansion or reduction shall be considered.
For viewing the parking situation of parking lot and lane change, because there is no traversal function for stl queue and stack, another container is used for traversal to determine whether to store in reverse order according to their respective characteristics.

3. Experiment code:

#include<bits/stdc++.h>
using namespace std;
const int maxn=110;
struct node
{
    string id;///License plate number
    int flag;///Indicates whether to arrive or leave: arrival is 1 and departure is 0
    int time;///Indicates the time of arrival or departure
};
map<string,bool>mp;///Is there a car in the parking lot
int n,cost;//Capacity of parking lot and parking fee per hour 
stack<node>stk;///Stack simulated parking lot 
queue<node>q;///Queue simulated Lane 

void showmain()//Print menu 
{
    cout<<"**********menu*************"<<endl;
    cout<<"1.Modify the capacity of the parking lot"<<endl;
    cout<<"2.Enter vehicle information"<<endl;
    cout<<"3.Modify the cost of parking for one hour"<<endl;
    cout<<"4.Check the condition of vehicles in the parking lot"<<endl;
    cout<<"5.Check the condition of vehicles changing lanes"<<endl;
    cout<<"6.Exit the system"<<endl;
}

void change_n()///Modify parking lot capacity: pay attention to the vehicles in the modified parking lot and lane change 
{
    int tmp;
    cin>>tmp;
    if(tmp>n)
    {///The expansion shows that more cars can enter the parking lot, take out the lane changing elements in turn and put them into the parking lot until it is full 
        while(stk.size()<=n)
        {
            node t=q.front();
            t.time=t.time;
            q.pop();
            stk.push(t);
            mp[t.id]=1;
        }
    }
    else
    {///After volume reduction, the car in the parking lot shall be moved to lane change 
        while(stk.size()>n)
        {
            node t=stk.top();
            stk.pop();
            mp[t.id]=0;
            q.push(t);
        }
    }
    n=tmp;
}

void change_cost()
{
    cin>>cost;
}

void add_car()
{
    cout<<"Please enter information about the vehicle:"<<endl;
    node t;
    cin>>t.id>>t.flag>>t.time;
    if(t.flag) //arrive
    {
        if(stk.size()==n)
        {
            q.push(t);///The parking lot is full and only stops on the road
            cout<<"The license plate number is"<<t.id<<"My car is on the road"<<q.size()<<"No. position"<<endl;
        }
        else
        {
            stk.push(t);///Park the car directly in the parking lot
            cout<<"The license plate number is"<<t.id<<"My car is in the parking lot"<<stk.size()<<"No. position"<<endl;
            mp[t.id]=1;
        }
    }
    else ///Leave
    {
        if(!mp[t.id])
        {
            puts("There is no such car in the parking lot");
            return ;
        }
        mp[t.id]=0;
        node tt=stk.top();
        stk.pop();
        while(stk.size()<n&&!q.empty())///The vacant parking space allows vehicles changing lanes to enter 
        {
            node tmp=q.front();
            tmp.time=t.time;
            q.pop();
            stk.push(tmp);
            mp[tmp.id]=1;
        }
        cout<<"The license plate number is"<<t.id<<"The cost of your car is"<<(t.time-tt.time)*cost<<endl;
    }
  ///  cout<<stk.size()<<"*************"<<q.size()<<endl;// Special for debug 
}

void show_park()///Check the condition of vehicles in the parking lot 
{
    ///In and out
    vector<node>v;
    int cnt=stk.size();
    while(!stk.empty()){//Take out the elements in the stack in turn 
        v.push_back(stk.top());
        cout<<"The license plate number is"<<stk.top().id<<"My car is in the parking lot"<<cnt--<<"No. position"<<endl;
        stk.pop();
    }
    reverse(v.begin(),v.end());//Because the stack is first in and last out, it needs to be turned over 
    for(int i=0;i<v.size();i++){//Put it back on the stack 
        stk.push(v[i]);
    }
}

void show_road()//Check the condition of vehicles changing lanes 
{
    vector<node>v;
    int cnt=1;
    while(!q.empty()){//Take out the elements in the queue in turn 
        v.push_back(q.front());
        cout<<"The license plate number is"<<q.front().id<<"My car is on the road"<<cnt++<<"No. position"<<endl;
        q.pop();
    }
    for(int i=0;i<v.size();i++){///Put back in queue 
        q.push(v[i]);
    }
}

int main()
{
    puts("Please enter the capacity of the parking lot:");
    cin>>n;
    puts("Please enter the fee for parking for one hour:");
    cin>>cost;
    while(1)
    {
        showmain();
        cout<<"Please enter what you want to do:"<<endl;
        int op;
        cin>>op;
        if(op==1) change_n();
        else if(op==2) add_car();
        else if(op==3) change_cost();
        else if(op==4) show_park();
        else if(op==5) show_road();
        else if(op==6) return 0;
    }
    return 0;
}

4. Operation results:

5. Experimental experience:

The inaccurate calculation of the cost is mainly reflected in the following aspects: 1. Because there is no charge for staying on the lane change, the change of parking lot capacity may have an impact on the residence time of some vehicles. 2. 2. After the change of parking cost per unit time, there are two costs before and after the change, which should be calculated separately.

3, Operation of binary tree

1. Experimental contents:

1. Experimental purpose:
(1) Master the basic algorithm of binary tree;
(2) Understand the change of node relationship after the tree is transformed into binary tree, and be able to solve practical problems.
2. Experimental content: the design of genealogy is mainly to realize the functions of establishing, searching, inserting, modifying and deleting family member information. Requirements and basic functions are as follows
(1) Two storage structures are used to realize the function of genealogy management, one of which is the linked list storage structure of children's brothers.; (2) Addition of family members: that is, add a person's children. The number of children is given by the control console, and then enter the corresponding children's names (the children's names here cannot be duplicate).
(2) Modification of family members: you can modify the name of a member.
(3) Member query: query the generation (generation) of a member in the family, and can query all the children of this member and all members of this generation.
(5) Deletion of family members: when deleting this member, if it has descendants, all its descendants will be deleted

2. Design idea:

First of all, it should be clear that the storage method is the child brother linked list storage method, that is, the pointer field of each node stores the first child of the node and the next brother of the node. Then talk about the design ideas in turn:
1. Tree building: first enter the root node, then enter the child nodes of each node in turn, and complete the tree building with the help of queue.
2. The function of finding the parent node: the essence is the traversal of the tree. After changing the storage mode, the design idea also changes slightly. First, if the node to be queried is the root node, NULL is returned directly; Then put the root node into the queue and take out the first element of the queue in turn. If the node has children, if the first child is the node to be queried, return to the node; Otherwise, it will traverse the child of the node, that is, the brother node of the first child of the node. If a brother node is a node to be queried, it will also return the node.
3. Add function: it only implements the function of adding a child, such as adding son to fa. Find the fa node first. If the node has no children, then son is his first child; Otherwise, the first child's sibling node of fa is traversed to the end, and then son is connected.
4. Delete function: judge whether the element to be deleted is the first child; First find the parent node of the element to be deleted. If the element to be deleted is the first child, move the pointer back directly; Otherwise, find the node first, and then move the pointer back.
5. Query function: it's a bit opportunistic here. First, the depth of each node is stored by hierarchical traversal. Therefore, for each node, the depth of the same generation is the same, and all its child nodes are all nodes with a greater depth than him. Because of the hierarchical traversal time, we assume that the depth of the root node is 1
6. Modify function: find the node and modify it.

3. Experiment code:

#include<bits/stdc++.h>
using namespace std;
/**Initialized state definition start**/
#define OK 1
#define ERROR 0
#define FALSE 0
#define TRUE 1
#define OVERFLOW -2
typedef int Status;
typedef char ElemType;
/**Initialized state definition end**/
/**Structure definition of binary tree start**/
typedef struct CSNode
{
    ElemType data;
    struct CSNode *firstChild;///First child
    struct CSNode *nextsbling;///The child's next brother
} CSNode,*CSTree;
/**Structure definition of binary tree**/
/**Queue definition start**/
typedef CSTree QElemType;
typedef struct QNode
{
    QElemType data;//Data domain 
    struct QNode *next;//Pointer field 
} QNode,*QueuePtr;//Linked list 
typedef struct
{
    QueuePtr Front;///Queue head pointer
    QueuePtr Rear;///Tail pointer
} LinkQueue;
Status InitQueue(LinkQueue &Q)
{
    ///Initialize queue
    Q.Front=Q.Rear=(QueuePtr)malloc(sizeof(QNode));
    if(!Q.Front)
        exit(OVERFLOW);///Failed to request memory
    Q.Front->next=NULL;
    return OK;
}
Status QueueEmpty(LinkQueue Q) ///Determine whether the queue is empty
{
    if(Q.Front==Q.Rear)
        return TRUE;
    return FALSE;
}
Status EnQueue(LinkQueue &Q,QElemType e) ///Insert element
{
    QueuePtr t=(QueuePtr)malloc(sizeof(QNode));
    if(!t)
        exit(OVERFLOW);
    t->data=e;
    t->next=NULL;
    Q.Rear->next=t;
    Q.Rear=t;
    return OK;
}
Status DeQueue(LinkQueue &Q,QElemType &e)
{
    ///Take the team head element and assign it to e
    if(QueueEmpty(Q))
        return ERROR;///Queue is empty
    QueuePtr t=Q.Front->next;
    e=t->data;
    Q.Front->next=t->next;
    if(Q.Rear==t)
        Q.Rear=Q.Front;
    free(t);///Free up space
    return OK;
}
/**Queue definition end**/
/**Binary tree operation definition start**/
Status CreateTree(CSTree &T) ///Create a family tree
{
    LinkQueue Q;
    InitQueue(Q);///Construct queue and initialize
    char buffChild[20];///For temporary storage of children
    memset(buffChild,0,sizeof buffChild);///Initialization
    getchar();
    cout<<"Please enter the root node(Enter as characters,#Represents empty node): "< < endl;
    scanf("%c",&buffChild[0]);
    ///Cout < < buffchild [0] < < "*********************************************************************** 
    if(buffChild[0]!='#'/ / / if you have a first child 
    {
        T=(CSNode*)malloc(sizeof(CSNode));
        if(!T)
            exit(OVERFLOW);///Failed to request memory
        T->data=buffChild[0];
        T->nextsbling=NULL;///The root node has no siblings
        EnQueue(Q,T);///Root node queue
        while(!QueueEmpty(Q))
        {
            QElemType e;
            DeQueue(Q,e);///Get team leader element
            printf("Please enter a node%c My child(Enter the string in#End): ", e - > data);
            scanf("%s",buffChild);
            if(buffChild[0]!='#'/ / have children
            {
                CSTree q=(CSTree)malloc(sizeof(CSNode));///Open up children's node space
                if(!q)
                    exit(OVERFLOW);
                q->data=buffChild[0];
                e->firstChild=q;///Point to the first child
                EnQueue(Q,q);///Join the first child in the team
                CSTree p=q;///Point to the children who have just joined the team
                for(int i=1; i<strlen(buffChild)-1; i++)///Stored in sibling nodes in turn 
                {
                    q=(CSTree)malloc(sizeof(CSNode));
                    if(!q)
                        exit(OVERFLOW);
                    q->data=buffChild[i];
                    p->nextsbling=q;
                    EnQueue(Q,q);///Join the team
                    p=q;///Point to the children who have just joined the team
                }
                p->nextsbling=NULL;///The last one has no back brother
            }
            else
                e->firstChild=NULL;///No children
        }
    }
    else
        T=NULL;///Empty tree
    return OK;
}
Status TreeEmpty(CSTree T) ///Judge whether the tree with T as the root node is empty
{
    if(T)
        return TRUE;
    else
        return FALSE;
}
CSNode* FindNode(CSTree T,ElemType val)
{
    ///Query node with value val 
    LinkQueue Q;
    InitQueue(Q);///Construct and initialize queues
    if(T)
    {
        EnQueue(Q,T);
        while(!QueueEmpty(Q))
        {
            QElemType e;
            DeQueue(Q,e);
            if(e->data==val)
                return e;
            if(e->firstChild)
                EnQueue(Q,e->firstChild);
            if(e->nextsbling)
                EnQueue(Q,e->nextsbling);
        }
    }
    return NULL;
}
Status Change(CSTree &T,ElemType val,ElemType upd) ///Modify the name of a member
{
    CSTree p=FindNode(T,val);//Find the member and modify it directly 
    if(p==NULL)
        return FALSE;
    p->data=upd;
    return TRUE;
}
CSNode* Parent(CSTree T,ElemType val) ///Find parent node
{
    LinkQueue(Q);
    InitQueue(Q);///Construct and initialize queues
    if(T)
    {
        if(T->data==val)
            return NULL;///The root node has no parent node
        EnQueue(Q,T);
        while(!QueueEmpty(Q))
        {
            QElemType e;
            DeQueue(Q,e);
            QElemType p=e;///Defined as team leader element
            if(e->firstChild) ///If the node has children
            {
                if(e->firstChild->data==val)
                    return p;///The first child is what you want
                EnQueue(Q,e->firstChild);
                QElemType bro=e->firstChild->nextsbling;///The child's brother
                while(bro)
                {
                    if(bro->data==val)
                        return p;///The sibling node is the node to be requested
                    EnQueue(Q,bro);
                    bro=bro->nextsbling;
                }
            }
        }
    }
    return NULL;
}
ElemType Insert(CSTree &T,ElemType val,ElemType s) ///Insert node
{
    CSTree q=(CSTree)malloc(sizeof(CSNode));
    if(!q)
        exit(OVERFLOW);
    q->data=s;
    q->firstChild=NULL;
    q->nextsbling=NULL;///Child node
    CSNode* node=FindNode(T,val);///Find his parents
    if(node->firstChild) ///I already have my first child
    {
        node=node->firstChild;
        while(node->nextsbling)
            node=node->nextsbling;
        node->nextsbling=q;
    }
    else
        node->firstChild=q;
}
map<char,int>mp;
Status LevelOrderTraverse(CSTree T)  ///Hierarchical traversal
{
    cout<<"The hierarchy traversal result is"<<endl;
    int cnt=1;
    LinkQueue Q;
    InitQueue(Q);
    if(T)
    {
        printf("%c ",T->data); ///Access node
        mp[T->data]=cnt;
        EnQueue(Q,T);             ///Root node queuing
        while(!QueueEmpty(Q))
        {
            QElemType e,p;
            DeQueue(Q,e);
            p = e->firstChild;
            cnt++;
            while(p)
            {
                printf("%c ",p->data);
                mp[p->data]=cnt;
                EnQueue(Q,p);
                p = p->nextsbling;
            }
        }
        puts("");
        return OK;
    }
    return ERROR;
}
ElemType Delete(CSTree &T,ElemType val)
{
    CSNode* node=Parent(T,val);///Parent node found
    if(node->firstChild->data==val)
    {
        ///The first child is the element to be deleted
        node->firstChild=node->firstChild->nextsbling;
    }
    else
    {//Traverse the sibling node to find the element to be deleted 
        node=node->firstChild;
        while(node->nextsbling->data!=val)
            node=node->nextsbling;
        node->nextsbling=node->nextsbling->nextsbling;
    }
}
void FindBro(CSTree T,ElemType val)
{
    cout<<"People of the same generation are:"<<endl;
    for(map<char,int>::iterator  t=mp.begin(); t!=mp.end(); t++)
        if(t->second==mp[val]&&t->first!=val)
            cout<<t->first<<" ";
    puts("");
}
void FindChirld(CSTree T,ElemType val)
{
    cout<<"The person's children have"<<endl;
    for(map<char,int>::iterator t=mp.begin(); t!=mp.end(); t++)
        if(t->second>mp[val])
            cout<<t->first<<" ";
    puts("");
}
/**Operation definition of binary tree**/
/**Print menu start**/
void showmain()
{
    cout<<"Welcome to the genealogy management system"<<endl;
    cout<<"Please enter what you want to do"<<endl;
    cout<<"1.Establish genealogical tree"<<endl;
    cout<<"2.Add family members"<<endl;
    cout<<"3.Change the name of a family member"<<endl;
    cout<<"4.Delete a family member"<<endl;
    cout<<"5.Query a family member"<<endl;
    cout<<"6.Exit the system"<<endl;
}
/**Print menu end**/
/**Menu function body start**/
void AddPeople(CSTree &T)
{
    cout<<"Please enter the name of the father of the person you want to add"<<endl;
    char fa;
    cin>>fa;
    cout<<"Please enter the name of the child of the person you want to add"<<endl;
    char son;
    cin>>son;
    Insert(T,fa,son);

}
void UpdatePeople(CSTree &T)
{
    cout<<"Please enter the old name of the person whose name you want to change"<<endl;
    char old;
    cin>>old;
    cout<<"Please enter the new name of the person whose name you want to change"<<endl;
    char New;
    cin>>New;
    Change(T,old,New);
}
void DeletePeople(CSTree &T)
{
    cout<<"Please enter the name of the person you want to delete"<<endl;
    char del;
    cin>>del;
    Delete(T,del);
}
void FindPeople(CSTree &T)
{
    cout<<"Please enter the name of the person you want to find"<<endl;
    char name;
    cin>>name;
    cout<<"The person is in the second position"<<mp[name]<<"Generation"<<endl;
    LevelOrderTraverse(T);
    FindBro(T,name);
    FindChirld(T,name);
}
/**Function body of menu**/
int main()
{
    CSTree T;
    while(1)
    {
        showmain();
        int op;
        cin>>op;
        if(op==1)
            CreateTree(T);
        else if(op==2)
            AddPeople(T);
        else if(op==3)
            UpdatePeople(T);
        else if(op==4)
            DeletePeople(T);
        else if(op==5)
            FindPeople(T);
        else if(op==6)
            return 0;
        LevelOrderTraverse(T);
    }
    return 0;
}

4. Operation results:

5. Experimental experience:

After modification, the value of the array of nodes that do not update the record depth. Only one child can be added when adding members.

4, Operation of diagram

1. Experimental contents:

1. Experimental purpose:
(1) Master backtracking algorithm;
(2) Master the depth first and breadth first search algorithms of graph and use them to solve practical problems;
2. Experimental content: maze solution: a rectangular matrix of m*n is used to represent the maze, and 0 and 1 represent the paths and obstacles in the maze respectively. Design a program to find a path from the entrance to the exit for any set maze, or draw the conclusion that there is no path. The requirements are as follows:
(1) Firstly, a stack type is implemented, and the maze path (non recursive program) is solved by backtracking method. The obtained path is output in the form of triples (i,j,d), where (i,j) indicates a coordinate in the maze, and D indicates the direction to the next coordinate.
(2) The storage structure of the graph is established, and the maze path is obtained by depth first search. The output mode is self-defined, which can be used if it is simple and clear.
(3) The maze path is obtained by breadth first search. The output mode is self-defined, which can be used if it is simple and clear. (4) If there are multiple paths, how to find the shortest path?

2. Design idea:

It is divided into several aspects:
1. Maze generation: it can be entered manually or generated by prim algorithm.
2. Non recursive stack: the general idea is still similar to that of dfs, that is, go all the way around. If the road is blocked, go back to the previous step, which can be realized with the help of stack. For the input required by the content, d indicates the direction of going to the next coordinate. When we go to this step, we can not record the direction of this step in the final path. We can only record the direction from the previous step to this step. Just record the direction every time and then enter the stack.
3.dfs: you can find all the paths of the maze. Just go straight. The code is very short with the help of recursion. If you want to output the path, you'd better use the stack.
4.bfs: output the shortest path of the maze. The idea is similar to hierarchical traversal. Maintain it with the queue every time. If you record the path, record the point from which it came, and then push it back from the end.

3. Experiment code:

#include<bits/stdc++.h>
using namespace std;
int n,m;///Maze size: rows and columns 
int mp[110][110];//Map 
struct node///A node: coordinates and from which point 
{
    int x,y;
    string dir;
};
bool check(node t)///Judge whether a node can go
{
    int x=t.x,y=t.y;
    if(x>=1&&x<=n&&y>=1&&y<=m&&!mp[x][y]) return 1;
    return 0;
}
void init()
{
    ///Input maze
    cin>>n>>m;
    for(int i=1; i<=n; i++)
        for(int j=1; j<=m; j++)
            cin>>mp[i][j];
}
void findpath1()///Non recursive solution of maze path
{
    stack<node>stk;//With the help of stack 
    node now= {1,1,"0"};//Define work pointer 
    stk.push({1,1,"0"});
    while(!stk.empty())
    {
        node t=stk.top();//Take out the elements in the stack every time 
        if(t.x==n&&t.y==m)//Come to the end 
        {
            break;
        }
        node ne=t;
        mp[t.x][t.y]=2;//The point passed is marked as 2 

        ne=t;
        ///Traverse four directions respectively: if the direction can go, put the direction into the stack. At this time, update the direction of the previous node, that is, how the previous node arrived 
        ne.x--;
        if(check(ne))
        {
            t.dir="up";
            stk.pop();
            stk.push(t);
            stk.push(ne);
            continue;
        }
        ne=t;
        ne.x++;
        if(check(ne))
        {
            t.dir="down";
            stk.pop();
            stk.push(t);
            stk.push(ne);
            continue;
        }
        ne=t;
        ne.y--;
        if(check(ne))
        {
            t.dir="left";
            stk.pop();
            stk.push(t);
            stk.push(ne);
            continue;
        }
        ne=t;
        ne.y++;
        if(check(ne))
        {
            t.dir="right";
            stk.pop();
            stk.push(t);
            stk.push(ne);
            continue;
        }
        t=stk.top();
        stk.pop();
        mp[t.x][t.y]=3;
    }
    ///Output in reverse order 
    vector<node>v;
    while(!stk.empty())
    {
        v.push_back(stk.top());
        stk.pop();
    }
    reverse(v.begin(),v.end());
    for(int i=0; i<v.size(); i++) cout<<v[i].x<<" "<<v[i].y<<" "<<v[i].dir<<endl;
}

stack<node>path,tmp;//Store final and temporary paths 
int nx[]= {0,0,1,-1};//Directional function 
int ny[]= {1,-1,0,0};
int vis[110][110];//Tag array 
int cnt=0;//Record how many paths there are 
void findpath2(int x,int y) ///dfs solves all paths of maze
{
    if(x==n&&y==m)//Reach the end 
    {
        cout<<"***************route"<<++cnt<<"*****************"<<endl;
        while(!path.empty())//Output path 
        {
            tmp.push(path.top());
            path.pop();
        }
        while(!tmp.empty())
        {
            cout<<"("<<tmp.top().x<<","<<tmp.top().y<<")"<<endl;
            path.push(tmp.top());
            tmp.pop();
        }
        return ;
    }
    if(x<1||x>n||y<1||y>m) return ;
    for(int i=0; i<4; i++)//Traverse four directions 
    {
        int xx=x+nx[i],yy=y+ny[i];
        if(xx>=1&&xx<=n&&yy>=1&&yy<=m&&!mp[xx][yy]&&vis[xx][yy]==0)
        {//Leave legally 
            vis[xx][yy]=1;
            path.push({xx,yy});
            findpath2(xx,yy);
            vis[xx][yy]=0;
            path.pop();
        }
    }
}
queue<node>q;
int dis[110][110],fx[110][110],fy[110][110];
void Prinpath3(int x,int y)///bfs print path recursive print
{
    if(x!=-1&&y!=-1)
    {
        Prinpath3(fx[x][y],fy[x][y]);
        cout<<"("<<x<<","<<y<<")"<<endl;
    }
}
void findpath3()///bfs solving the shortest path
{
    memset(dis,-1,sizeof dis);///Initialize distance array
    q.push({1,1});///Put the starting point in the queue
    dis[1][1]=0;///Initialization distance
    fx[1][1]=fy[1][1]=-1;///Represents the coordinates of the previous point of this point
    while(!q.empty())//Queue element extension every time 
    {
        node now=q.front();
        q.pop();
        for(int i=0; i<4; i++)
        {
            node nex;
            nex.x=now.x+nx[i],nex.y=now.y+ny[i];
            if(check(nex)&&dis[nex.x][nex.y]==-1)
            {
                q.push(nex);
                dis[nex.x][nex.y]=dis[now.x][now.y]+1;//Equivalent to the expansion of hierarchical traversal 
                fx[nex.x][nex.y]=now.x;//Record which node this node came from 
                fy[nex.x][nex.y]=now.y;
            }
        }
    }
    Prinpath3(n,m);//Recursive print path 
}
int main()
{
    init();
  // findpath1();
   //  findpath2(1,1);
     findpath3();
    return 0;
}
/*
3 3
0 1 1
0 1 1
0 0 0
*/

4. Operation results:

5. Experimental experience:

5, Application of sorting algorithm

1. Experimental contents:

1. Experimental purpose:
(1) Master the commonly used internal sorting methods and compare them.
2. Experimental content: N random integers (more than 20000) are generated by random function, and these numbers are sorted by various methods. requirement:
(1) At least three methods are used to solve the above problems (hint, the available methods are Hill sort, bubble sort, quick sort, selection sort and heap sort). And save the sorted results in different files.
(2) Count the performance of each sorting method (compare it based on the time spent running the program on the computer), and find out two faster methods.

2. Design idea:

1. Calculation of data generation and time spent running the program: the former is generated by random numbers. Remember to add random number seeds to the main function; The latter uses clock_t variable and clock() function;
2. Bubble sort: O (n^2)
Two layers of for loop comparison, moving the smallest or largest to the beginning or end each time.
3. Quick sort: O (nlgn)
Each time you select a benchmark, put the smaller one in the front and the larger one in the back, and deal with the left and right parts recursively. Each time, the sorting range is changed to half of the original to improve efficiency.
4. Hill sort: O(n^(1.3-2))
An efficient and improved version of insert sorting. Each time, the elements with the same subscript spacing are sorted to make parts orderly and improve efficiency.

3. Experiment code:

#include<bits/stdc++.h>
using namespace std;
const int maxn=20000+100;
int a[maxn],n,b[maxn];
void sortloop(int n,int *b)///Bubble sorting 
{
    for(int i=1; i<n; i++)
    {
        for(int j=i+1; j<=n; j++)
            if(b[i]>b[j]) swap(b[i],b[j]);
    }
}
void sortquick(int l,int r,int *b)//Quick sort 
{
	//Each time you select a datum element, move the smaller one in front of him and the larger one behind him
	//The specific implementation is to set the head and tail pointers, and move two pointers each time. When the element position needs to be modified, the position of one element must be empty and the assignment can be done 
  	//Then the position of the reference element must be determined, and the left and right parts can be solved recursively 
    if(l<r)
    {
        int val=b[l];
        int low=l,high=r;
        while(low<high)
        {
            while(b[high]>=val&&low<high) high--;
            b[low]=b[high];
            while(b[low]<=val&&low<high) low++;
            b[high]=b[low];
        }
        a[low]=val;
        sortquick(l,low-1,b);///Pay attention to boundary treatment 
        sortquick(low+1,r,b);
    }
}
void sortshell(int n,int *b){///Hill sort
//Elements with the same subscript spacing are sorted each time until the spacing is 1 
    /*for(int gap=2*n;gap;gap=gap/2){//Enumeration spacing 
        for(int i=gap;i<=n;i++){//Enumeration element 
            for(int j=i-gap;j>=1;j-=gap){//Enumerate the elements before this element 
                if(b[j]>b[j+gap]) swap(b[j],b[j+gap]);///Violence is not optimized
            }
        }
    }*/
    for(int gap=2*n;gap;gap=gap/2){///Enumeration spacing 
        for(int i=1;i<=gap;i++){///gap group
            for(int j=i+gap;j<=n;j+=gap){//Enumerate the first element 
                if(b[j]<b[j-gap]){///When traversing backward in turn, compare with the previous elements with the help of the principle of monotonic stack 
                    int tmp=b[j],q=j-gap;
                    while(q>=1&&b[q]>tmp){
                        b[q+gap]=b[q];q-=gap;
                    }
                    b[q+gap]=tmp;
                }
            }
        }
    }
}
int main()
{
    srand(time(0));//Random number seed
    clock_t s,e;
    n=10000;
    ///n=(rand()*rand()+rand())%20000+1;/// Length of randomly generated array
    for(int i=1; i<=n; i++)
    {
        a[i]=(rand()*rand()+rand())%10000+1;///Randomly generate elements in the array
        b[i]=a[i];///Copy
    }
    s=clock();///Calculate code run time
    sortloop(n,b);
    e=clock();
    cout<<"Bubble sort took:"<<(double(e-s)/CLOCKS_PER_SEC)<<"s\n";

    s=clock();///Calculate code run time
    for(int i=1; i<=n; i++) b[i]=a[i];
    sortquick(1,n,b);
    e=clock();
    cout<<"The time taken for quick sort is:"<<(double(e-s)/CLOCKS_PER_SEC)<<"s\n";

    s=clock();///Calculate code run time
    for(int i=1; i<=n; i++) b[i]=a[i];
    sortshell(n,b);
    e=clock();
    cout<<"The time spent sorting is:"<<(double(e-s)/CLOCKS_PER_SEC)<<"s\n";

    return 0;
}

Tags: Algorithm data structure linked list

Posted on Thu, 02 Dec 2021 15:46:59 -0500 by kenshintomoe225