Data structures and algorithms

Keywords: C++ Algorithm data structure Autonomous vehicles

#Data structure and algorithm Introduction

There is no best algorithm in the world, only the most suitable algorithm

Logical structure




Physical structure





Talk about algorithm









Algorithm time complexity

















Just tell you to pay attention to the highest order, then ignore the constant product of constant and order, and pay attention to enough data.

The number of executions is the time




















Algorithm space complexity



Linear table





Abstract data type









void unionL(List* La, List* Lb)//This pseudo code is to insert data different from La in Lb into La in turn
{
	int La_len, Lb_len, i;

	ElemType e;
	La_len = ListLength(*La);

	Lb_len = ListLength(*Lb);

	for (int i=1;i<=Lb_len;i++)//This is written as a data structure algorithm, because the focus is on the algorithm process, not let the compiler understand it
	{
		GetElem(Lb, i, &e);
		if (!Locate(*La,e))
		{
			ListInsert(La, ++La_len, e);
		}
	}
}

Sequential storage structure of linear table



Address calculation method



This should be O(1), not 0 (1).

Get element operation


typedef int Status;

Status GetElem(Sqlist L,int i,ElemType *e)
{
	if (L.length == 0 || i<i || i>L.length)//The linear table starts with 1
	{
		return ERROR;
	}
	*e = L.data[i - 1];

	return OK;
}

Insert operation



Status ListInsert(Sqlist *L, int i, ElemType e)
{
	int k;
	if (L->length == MAXSIZE)//The sequence table is full
	{
		return ERROR;
	}
	if (i<1 || i>L->length + 1)//i out of range
	{
		return ERROR;
	}
	if (i <= L->length)
	{
		for (k = L.length - 1; k >= i - 1; k--)
		{
			L->data[k + 1] = L->data[k];//Element backward
		}
	}
	L->data[i - 1] = e;
	L->length++;
	return OK; 
}

Delete operation

//delete
//Output the i th element of L and use e to return the deleted value.
Status ListDelete(Sqlist* L, int i, ElemType e)
{
	if (L - length == 0)
	{
		return ERROR;
	}
	if (i<1 || i>L->length )//i out of range
	{
		return ERROR;
	}
	e = L->data[i - 1];
	if (i <= L->length)
	{
		for (k = i; k < L->length; k++)
		{
			L->data[k - 1] = L - data[k];
		}
		
	}
	L->length--;
	return e;
}

Advantages and disadvantages of linear table sequential storage structure


Chain storage structure of linear list









You can see that the null pointer points to the header node.
The node behind the head node is the one that really stores data.


Single linked list reading

//obtain
	Satus GetElem(LinkList *L, int i, ElemType* e)
	{
		int j;
		LinkList p;
		p = L->next;//p points to the first node
		j = 1;
		while (p && j < i)//When jumping out of the loop, normally it should be i==j
		{
			p = p->next;
			++j;
		}
		if (p! || j > i)//If p points to null or what you want to find doesn't exist at all
		{
			return ERROR;
		}
		*e = p->data;
		return OK;
	}

Single linked list insert




	//Single linked list insert
	//Insert a new element e after the ith position in L, the length of L plus 1
	Status ListInsert(LinkList* L, int i, ElemType* e)
	{
		int j;
		LinkList* p;
		LinkList* s;
		p = L->next;//p points to the first node
		j = 1;
		while (p && j < i)//When jumping out of the loop, normally it should be i==j
		{
			p = p->next;
			++j;
		}
		if (p!|| j > i)//If p points to null or what you want to find doesn't exist at all
		{
			return ERROR;
		}
		s = (LinkList)malloc(sizeof(Node));//Allocate a memory space to the new node S
		s->data = *e;
		//The following two sentences must not be written backwards. The consequences were ptt mentioned earlier.
		s->next = p->next;
		p->next = s;
		return OK;
	}



	//Single linked list deletion
	//Delete the ith Node and return the data in it
	Status ListDelete(LinkList* L, int i, ElemType* e)
	{
		int j;
		LinkList* p;
		LinkList* q;
		p = L->next;//p points to the first node
		j = 1;
		while (p && j < i-1)//When jumping out of the loop
		{
			p = p->next;
			++j;
		}
		if (p!|| j > i)//If p points to null or what you want to find doesn't exist at all
		{
			return ERROR;
		}
		q = p->next;//q points to the ith node
		p -> next = q -> next;
		*e = q->data;
		delete q;
		return OK;

	}

Efficiency PK



It can be seen that the advantages of single linked list in inserting and deleting multiple data are significantly greater than that of sequential storage structure.

Whole table creation of single linked table


Establishing single linked list by head interpolation



Insert the code slice here
	//Single chain meter insertion
	void CreateListHead(LinkList* L, int n)
	{
		LinkList p;
		int i;
		srand(time(0));//Initialize random number seed

		*L = (LinkList)malloc(sizeof(Node));
		(*L)->next = NULL;
		for (int i = 0; i < n; i++)
		{
			p = (LinkList)malloc(sizeof(Node));//Generate new node
			p->data = rand() % 100 + 1;
			p->next = (*L)->next;
			(*L)->next = p;
		}
	}
	//Why is * l and the other is p, which means that l is a secondary pointer and the function passes in * L. we directly think that * l is a pointer to the linked list
	//This code is header insertion, but the header * L is still at the front.

Code flow chart

Establishing single linked list by tail interpolation



	//Single chain table tail insertion
	void CreateListTail(LinkList* L, int n)
	{
		LinkList p,r;
		int i;
		srand(time(0));//Initialize random number seed

		*L = (LinkList)malloc(sizeof(Node));
		r = *L;
		for (int i = 0; i < n; i++)
		{
			p = (Node *)malloc(sizeof(Node));//Generate new node
			p->data = rand() % 100 + 1;
			r->next = p;
			r = p;
		}

		r->next = NULL;
	}

Code flow

Whole table deletion of single linked list

	//Single linked list whole table deletion
	Status ClearList(LinkList* L)
	{
		LinkList p, q;
		p = (*L)->next;//p points to the first node
		while (p)
		{
			q = p->next;
			free(p);
			p = q;
		}
		(*L)->next = NULL;

		return OK;
	}

Advantages and disadvantages of single linked list structure and sequential storage structure



For the search, the sequential storage structure has a subscript, which can be found at once. The single linked list should be found one by one, because the address of the next node should be found from the next of the previous node.
Insertion and deletion are obvious, because the sequential storage structure needs to shift other elements, while the single linked list only needs to move the pointer to.


review




Static linked list







The cursor points to the next subscript


The cursor of the first space points to the subscript of the free space.
That is, at first, the cursor in the first space is 5, that is, the space with subscript 5 is idle, and then the cursor in the first space becomes 6
The cursor for the last non free space is represented by 0


Insertion of static linked list

First, get the subscript of the free element

	//Insert a new element e before the ith element in the static linked list L
	//It's a little difficult to understand the code. It's better to understand it in combination with the following figure
	Status ListInsert(StaticLinkList L.int i,ElemType e)
	{
		int j, k, l;
		k = MAX_SIZE - 1;//The last element, and the cursor of the last element is the subscript of the first element
		if (i<1 || i>ListLength(L)+1)//i out of normal range
		{
			return ERROR;
		}
		j = Mlloc_SLL(L);//Gets the subscript of the free element
		if(j)
		{
			L[j].data = e;
			for (l=1;l<=i-1;l++)
			{
				k = L[k].cur;
			}
			L[j].cur = L[k].cur;
			L[k].cur = j;
			return OK;
		}
		return ERROR;
	}

Code flow
Take i=2 as an example

Deletion of static linked list



	//Delete the ith element in L
	Status ListDelete(StaticLinkList L.int i)
	{
		int j, k;
		if (i<1 || i>ListLength(L) + 1)//i out of normal range
		{
			return ERROR;
		}
		k = MAXSIZE - 1;
		for (j = 1; j <= i - 1; j++)
		{
			k = L[k].cur;//k1 =1.k2=5
		}
		j = L[k].cur;//j=2
		L[k].cur = L[j].cur;//L[5].cur=3
		Free_SLL(L.j);//Here is to connect the spare free elements
		return OK;
	}

	//Idle nodes with subscript k will be affected by the standby linked list
	void Free_SLL(StaticLinkList space,int k)
	{
		space[k].cur = space[0].cur;
		space[0].cur = k;
	}

	//Returns the number of elements in L
	int ListLength(StaticLinkList L)
	{
		int j = 0;
		int i = L[MAXSIZE - 1].cur;
		while (i)
		{
			i = L[i].cur;
			j++
		}
		rturn j;
	}

Code flow




Advantages and disadvantages of static linked list

Summary of single linked list Tencent interview questions


	//Tencent interview questions, find the middle node
	Status GetMidNode(LinkList L.ElemType* e)
	{
		LinkList search, mid;
		search = mid = L;
		while (search->next!=NULL)
		{
			if (search->next->next != NULL)
			{
				search = search->next->next;
				mid = mid->next;
			}
			else
			{
				search = search->next;
			}
		}
		*e = mid->data;
		return OK;
	}

Circular linked list




//Circular linked list 
#include<iostream>
namespace xunhuanLinkList
{
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
    using namespace std;

    typedef struct cLinkList
    {
        int data;
        struct cLinkList * next;
    }node;


/*
*Insert node
* Parameters: the first node of the linked list, the insertion position
*/
    void ds_insert(node **pNode,int i)
    {
        node *temp;
        node* target;
        node* p;
        int item;
        int j = 1;
        cout<<"Enter the value of the node to insert"<<endl;
        cin >> item;

        if (i == 1)
        {//The newly inserted node acts as the first node
            temp= (node*)malloc(sizeof(struct cLinkList));

            if (!temp)
            {
                exit(0);
            }

            temp->data = item;
            //Find the last node
            for (target = (*pNode); target->next != (*pNode); target = target->next)
                ;

            temp ->next = (*pNode);
            target->next = temp;
            *pNode = temp;//The first node becomes temp

        }
        else
        {
            target = *pNode;

            for (; j < (i - 1); ++j)
            {
                target = target->next;
            }

            //target points to the i-1 element

            temp = (node*)malloc(sizeof(struct cLinkList));
            if (!temp)
            {
                exit(0);
            }
            temp->data = item;

            p = target ->next;//Point to the original i-th element
            target->next = temp;//The next of the i-1 element points to the new i-th element
            temp->next = p;//The new ith element points to the original ith element
        }
    }

/*
* Delete node
* Parameter: the first node of the linked list, the location of deletion
*/
    void ds_delete(node** pNode, int i)
    {
        node* temp;
        node* target;
        int j = 1;
        if (i == 1)
        {//Delete first node
            //Find the last node
            for (target = (*pNode); target->next != (*pNode); target = target->next)
                ;
            temp = *pNode;
            *pNode = (*pNode)->next;
            target->next = *pNode;
            free(temp);
        }
        else
        {
            target = *pNode;
            for (; j < (i - 1); ++j)
            {
                target = target->next;
            }
            temp = target->next;//
            target->next = temp->next;
            free(temp);
        }
    }

/*
* search Returns the location of the node value
* Parameter: the value of the linked list returned by the first node of the linked list
*/
    int ds_search(node* pNode, int elem)
    {
        node* target;
        int i = 1;
        for (target = pNode; target->data != elem && target->next != pNode; ++i)
        {
            target = target->next;
        }

        if (target->next != pNode)//I think there is a problem, because when target - > next = = pnode, it can also target - > data = = elem
            //if(target->data == elem)
        {
            return i;//The element does not exist in the table
        }
        else if(target->next == pNode &&target->data==elem)
        {
            return i;
        }
        else
        {
            return 0;
        }
    }

/*
* ergodic
* Parameter: the first node of the linked list
*/
    void ds_traverse(node *pNode)
    {
        node* temp;
        temp = pNode;
        cout<<""<<endl;
        do
        {
            cout<<temp->data<<endl;
        } while ((temp = temp->next) != pNode);
        cout<<endl;

    }

/*
* //Initialize linked list
* Parameter: the first node of the linked list
*/
    void ds_init(node **pNode)
    {
        int item;
        node *temp;
        node* target;
        cout<<"Enter the value of the node and enter 0 to complete the initialization"<<endl;

        while (1)
        {
            cin >> item;
            fflush(stdin);//Clear buffer

            if (item == 0)
            {
                return ;
            }

            if ((*pNode) == NULL)
            {//There is only one node in the circular linked list
                //There is no header node in this code. The header node is the first node, which also stores values
                *pNode = (node*)malloc(sizeof(struct cLinkList));
                if (!(*pNode))//*Exit if pNode is empty
                    exit(0);

                (*pNode)->data = item;
                (*pNode)->next = *pNode;
            }
            else
            {
                //Find the last node
                for (target = (*pNode); target->next != (*pNode); target = target->next)
                    ;
                temp = (node*)malloc(sizeof(struct cLinkList));
                //Generate a new node

                if (!item)
                    exit(0);
                temp->data = item;
                temp->next = *pNode;
                target->next = temp;
            }
        }
    }

    void test()
    {
        node* pHead = NULL;
        char opp;
        int find;
        int search;
        cout<<  "1.Initialize linked list"<<endl;
        cout << "2.Insert node" << endl;
        cout << "3.Delete node" << endl;
        cout << "4.Return node location" << endl;
        cout << "5.Traversal node" << endl;
        cout << "0.sign out" << endl;
        cout << "Please select your action" << endl;
        while (opp!='0')
        {
            cin >> opp;
            switch (opp)
            {
                case '1':
                    ds_init(&pHead);//
                    cout<<endl;
                    ds_traverse(pHead);
                    break;
                case '2':
                    cout<<"Please enter the location (node number) to insert:"<<endl;
                    cin>>find;
                    ds_insert(&pHead,find);//
                    cout<<endl;
                    ds_traverse(pHead);
                    break;
                case '3':
                    cout<<"Please enter the location (node number) to delete:"<<endl;
                    cin>>find;
                    ds_delete(&pHead,find);//
                    cout<<endl;
                    ds_traverse(pHead);
                    break;
                case '4':
                    cout<<"Please enter the value to query:"<<endl;
                    cin>>find;
                    search=ds_search(pHead,find);
                    cout<<"Found"<<find<<"The position of the is in the second"<<search<<"Nodes"<<endl;
                    cout<<endl;
                    ds_traverse(pHead);
                    break;
                case '5':
                    ds_traverse(pHead);
                    break;
                case '0':
                    exit(0);
            }

        }

    }
}
int main()
{
    xunhuanLinkList::test();
}

josephus problem



#include <iostream>

//josephus problem 
namespace josephus
{
    #include<stdlib.h>
    #include<stdio.h>
    #include <iostream>
    using namespace std;
    typedef struct node
    {
        int data;
        struct node *next;

    }node;

    node* creat(int n)
    {
        node* p = NULL, * head;
        head = (node*)malloc(sizeof(node));
        p = head;
        node* s;
        int i = 1;

        if (0 != n)
        {
            while (i<=n)
            {
                s= (node*)malloc(sizeof(node));
                s->data = i++;
                p->next = s;
                p = s;

            }
            s->next = head->next;//S - > next is the first node
        }
        free(head);//No need to release header node

        return s->next;
    }

    void test()
    {
        int n = 41;
        int m = 3;
        int i;
        node* p = creat(n);
        node* temp;
        m %= n;

        while (p!=p->next)
        {
            for (i = 1; i < m - 1; i++)
            {
                p = p->next;
            }
            cout<<p->next->data<<"->";
            temp = p->next;
            p->next = temp->next;
            free(temp);
            p = p->next;

        }

        cout << p->data << endl;
    }
}

int main(int argc, char** argv)
{
    josephus::test();
    return 0;
}

Characteristics of circular linked list





Determine whether the linked list has a ring




Code implementation of two methods




Overall code - not yet completed

#include<stdio.h>
#include<stdlib.h>
#include <time.h>
#include<iostream>
using namespace std;

typedef struct Node
{
    int data;
    struct Node * next;
}Node;
typedef struct Node *LinkList;//It means that what is defined by LinkList is a pointer
//Single chain meter insertion acyclic
void CreateListHead(LinkList * L, int n)
{
    LinkList p;
    int i;
    srand(time(0));//Initialize random number seed

    *L = (LinkList)malloc(sizeof( Node));
    (*L)->next = NULL;
    for (int i = 0; i < n; i++)
    {
        p = (Node *)malloc(sizeof(Node));//Generate new node
        p->data = rand() % 100 + 1;
        p->next = L->next;
        (*L)->next = p;
    }
}



int main() {
    std::cout << "Hello, World!" << std::endl;
    return 0;
}

Magician deal







The code is as follows:

#include <iostream>
#include<stdio.h>
#include<stdlib.h>

using namespace std;
static int CardNumber=13;
typedef struct Node
{
    int data;
    struct Node * next;
}sqlist,*LinkList;
typedef struct Node *LinkList;//It means that what is defined by LinkList is a pointer


/**
 * Generation of circular linked list
 */
 LinkList CreatLinkList()
{
     LinkList head=NULL;
     LinkList  s ,r;
     int i;
     r=head;
     for(int i=0;i<CardNumber;i++)
     {
         s=(LinkList) malloc(sizeof (sqlist));
         s->data=0;
         if(head==NULL)
             head=s;
         else
             r->next=s;

         r=s;
     }
     r->next=head;
    return head;
}


/**
 * Destruction work
 */
void DestoryList(LinkList *List)
{
    LinkList ptr=*List;
    LinkList buff[CardNumber];
    int i=0;
    while (i<CardNumber)
    {
        buff[i++]=ptr;
        ptr=ptr->next;
    }
    for(i=0;i<CardNumber;i++)
    {
        free(buff[i]);
    }
    *List=0;
}

/**
 * Licensing sequence calculation
 * @return
 */
void Magician(LinkList head)
{
    LinkList p;
    int j;
    int Countnumber=2;
    p=head;
    p->data=1;

    while (1)
    {
        for(j=0;j<Countnumber;j++)
        {
            p=p->next;
            if(p->data!=0)//If there is a card in this position, the next position
            {
                p->next;//p=p->next;??
                j--;
            }
        }

        if(p->data==0)
        {
            p->data=Countnumber;
            Countnumber++;
            if(Countnumber==14)
                break;;
        }
    }
}

int main() {
    LinkList  p;
    int i;
    p=CreatLinkList();
    Magician(p);

    cout<<"In the following order:"<<endl;
    for(i=0;i<CardNumber;i++)
    {
        cout<<"spade"<<p->data;
        p=p->next;
    }
    DestoryList(&p);
    return 0;
}

Latin matrix problem - assignment




In fact, it is printed in the order of rings
The code is as follows. I put the licensing and Latin matrix in one file.

#include <iostream>
#include<stdio.h>
#include<stdlib.h>

using namespace std;
static int CardNumber=13;
typedef struct Node
{
    int data;
    struct Node * next;
}sqlist,*LinkList;
typedef struct Node *LinkList;//It means that what is defined by LinkList is a pointer


/**
 * Generation of circular linked list
 */
 LinkList CreatLinkList(int n)
{
     LinkList head=NULL;
     LinkList  s ,r;
     int i;
     r=head;
     for(int i=0;i<n;i++)
     {
         s=(LinkList) malloc(sizeof (sqlist));
         s->data=0;//The default is 0
         if(head==NULL)
             head=s;
         else
             r->next=s;

         r=s;
     }
     r->next=head;
    return head;
}


/**
 * Destruction work
 */
void DestoryList(LinkList *List)
{
    LinkList ptr=*List;
    LinkList buff[CardNumber];
    int i=0;
    while (i<CardNumber)
    {
        buff[i++]=ptr;
        ptr=ptr->next;
    }
    for(i=0;i<CardNumber;i++)
    {
        free(buff[i]);
    }
    *List=0;
}

/**
 * Licensing sequence calculation
 * @return
 */
void Magician(LinkList head)
{
    LinkList p;
    int j;
    int Countnumber=2;
    p=head;
    p->data=1;

    while (1)
    {
        for(j=0;j<Countnumber;j++)
        {
            p=p->next;
            if(p->data!=0)//If there is a card in this position, the next position
            {
                p->next;//p=p->next;??
                j--;
            }
        }

        if(p->data==0)
        {
            p->data=Countnumber;
            Countnumber++;
            if(Countnumber==14)
                break;;
        }
    }
}


/**
 * Licensing problem test
 */
void Magician_Problem()
{
    LinkList  p;
    int i,n;
    //This is the licensing solution
    p=CreatLinkList(CardNumber);
    Magician(p);

    cout<<"In the following order:"<<endl;
    for(i=0;i<CardNumber;i++)
    {
        cout<<"spade"<<p->data;
        p=p->next;
    }
    cout<<endl;
    cout<<endl;
    //DestoryList(&p);
}


/**
 * Latin matrix problem
 * It is realized by circular linked list
 * For example, for a 3x3 Latin matrix, the first row is output from the first node, the second row is output from the second node, the third row vong is output from the third node. Output 3 data per row.
 * @return
 */
void LatinMatrix(LinkList head,int n)
{
    LinkList p;
    p=head;
    int j,i=1;
    for(j=0;j<n;j++,i++)
    {

        if(p->data==0)
        {
            p->data=i;
        }
        p=p->next;//point
    }
    p=head;
    //output

    /* debug See if the linked list is as we think
    for(int k=0;k<n;k++)
    {
        cout<<p->data<<" ";
        p=p->next;
    }*/

    int count=0;
    for(int k=0;k<n;k++)
    {

        for(int l=0;l<n;l++)
        {
            cout<<p->data;
            p=p->next;
        }
        p=head;
        count++;
        for(int m=0;m<count;m++)
        {
            p=p->next;
        }
        cout<<endl;

    }
}

/**
 * Latin matrix problem
 * @return
 */
void LatinMatrix_Problem()
{
    LinkList  p;
    int n;
    cout<<"Please enter the dimension of Latin matrix:"<<endl;
    cin>>n;
    p=CreatLinkList(n);
    LatinMatrix(p,n);
    cout<<endl;
    //DestoryList(&p);
}

int main() {


    int choice=1;
    while(choice)
    {
        cout<<"Please enter 1 to select a licensing question"<<endl;
        cout<<"Please enter 2 to select the Latin matrix question"<<endl;
        cout<<"Exit, please enter 0"<<endl;
        cin>>choice;
        switch (choice) {
            case 1 :
                Magician_Problem();
                break;
            case 2 :
                LatinMatrix_Problem();
                break;
            case 0 :
                exit(0);
                break;

        }
    }


    return 0;
}




Bidirectional linked list




Insertion of bidirectional linked list


Deletion of bidirectional linked list



Practice of double line circular linked list



#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace  std;
typedef char ElemType;
typedef int Status;
#define ERROR 0;
#define OK 1;
typedef struct DualNode
{
    ElemType data;
    struct DualNode *prior;//Precursor node
    struct DualNode *next;//Rear drive node
}DualNode ,*DuLinkList;

/**
 * Initialize linked list
 * *L Represents a pointer, then L is the pointer to the pointer?
 */
Status InitList(DuLinkList *L)
{
    DualNode*p,*q;
    int i;
    *L=(DuLinkList) malloc(sizeof (DualNode));
    if(!(*L))
    {
        return ERROR;
    }

    (*L)->next=(*L)->prior=NULL;
    p=(*L);//Now it's the head node. Don't assign it a value
    for(i=0;i<26;i++)
    {
        q=(DuLinkList) malloc(sizeof (DualNode));
        if(!q)
        {
            return ERROR;
        }
        q->data='A'+i;
        q->prior=p;

        q->next=p->next;//There's nothing here
        p->next=q;


        p=q;
    }

    p->next=(*L)->next;
    (*L)->next->prior=p;

    return OK;
}


void Caesar(DuLinkList *L,int i)
{
    if(i>0)
    {
        do
        {
            (*L)=(*L)->next;

        }while(--i);
    }
    if(i<0)//It's worth thinking about the source code. There's a problem with this one. I changed it
    {
        (*L)=(*L)->next;
        do
        {
            (*L)=(*L)->prior;

        }while(i++);
    }
}
int main() {
    DuLinkList L;
    int i,n;
    InitList(&L);//Pass in the address of pointer L, and the parameter of the function is * l, then * l is the pointer to the linked list inside the function
    cout<<"please enter an integer n:"<<endl;
    cin>>n;
    cout<<endl;
    Caesar(&L,n);

    for( i=0;i<26;i++)
    {
        L=L->next;
        cout<<L->data;

    }

    cout<<endl;
    return 0;
}

Vingenre encryption – job


The code is as follows. I put Vigenere together with the problem of alphabet sorting.

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <vector>
using namespace  std;
typedef char ElemType;
typedef int Status;
#define ERROR 0;
#define OK 1;
typedef struct DualNode
{
    ElemType data;
    struct DualNode *prior;//Precursor node
    struct DualNode *next;//Rear drive node
}DualNode ,*DuLinkList;

/**
 * Initialize linked list
 * *L Represents a pointer, then L is the pointer to the pointer?
 * Node containing header has no value
 */
Status InitList(DuLinkList *L)
{
    DualNode*p,*q;
    int i;
    *L=(DuLinkList) malloc(sizeof (DualNode));
    if(!(*L))
    {
        return ERROR;
    }

    (*L)->next=(*L)->prior=NULL;
    p=(*L);//Now it's the head node. Don't assign it a value
    for(i=0;i<26;i++)
    {
        q=(DuLinkList) malloc(sizeof (DualNode));
        if(!q)
        {
            return ERROR;
        }
        q->data='A'+i;
        q->prior=p;

        q->next=p->next;//There's nothing here
        p->next=q;


        p=q;
    }

    p->next=(*L)->next;
    (*L)->next->prior=p;

    return OK;
}

/**
 * Solution of alphabet problem
 * @param L
 * @param i
 */
void Caesar(DuLinkList *L,int i)
{
    if(i>0)
    {
        do
        {
            (*L)=(*L)->next;

        }while(--i);
    }
    if(i<0)
    {
        (*L)=(*L)->next;
        do
        {
            (*L)=(*L)->prior;

        }while(i++);
    }
}

/**
 * The alphabet is output at the specified position
 * @return
 */
void alpha_cout()
{
    DuLinkList L;
    int i,n;
    InitList(&L);//Pass in the address of pointer L, and the parameter of the function is * l, then * l is the pointer to the linked list inside the function
    cout<<"please enter an integer n:"<<endl;
    cin>>n;
    cout<<endl;
    Caesar(&L,n);

    for( i=0;i<26;i++)
    {
        L=L->next;
        cout<<L->data;

    }
    cout<<endl;
}

//Keys and ciphertext
struct mmWen
{
    int mishi;//key 
    char miwen='0';//ciphertext
};

/**
 * Vingenre Solution of encryption problem
 * A random number will be generated for each letter (make this number in the range of 0-49)
 * Then save the keys and inscriptions of each letter in the mmWen data structure corresponding to each letter
 * @return
 */
 void Vingenre()
{

     vector<mmWen> mmWem_;//Store the ciphertext and key corresponding to A-Z
    DuLinkList L,p;
    InitList(&L);//Pass in the address of pointer L, and the parameter of the function is * l, then * l is the pointer to the linked list inside the function

    //The text is as follows
    //debug to see if the output is the 26 letters you want
    cout<<"The plaintext and the corresponding key are as follows"<<endl;
    for(int i=0;i<26;i++)
    {
        L=L->next;
        cout<<L->data<<" ";
    }
    p=L->next;p Point to letter A Node of
    cout<<endl;
    srand((int)time(NULL));

    for(int i = 0; i < 26;i++ )
    {
        int j= rand()%9;

        cout <<j << " ";
        mmWen t;
        t.mishi=j;
        mmWem_.push_back(t);//Save key
    }
    cout<<endl;

/*    //debug Used to test whether the key is stored in the corresponding struct
    for(auto a:mmWem_)
    {
        cout<<a.mishi<<" ";
    }*/

    //Put the ciphertext and key directly in the container
    for(int i=0;i<26;i++)
    {
        //int m=(p->data)-'A';// Serial number corresponding to plaintext
        int n=i+mmWem_[i].mishi;//Get the letter sequence number corresponding to the key
        for(int j=0;j<n;j++)//Find the node corresponding to the ciphertext
        {
            p=p->next;
        }
        mmWem_[i].miwen=p->data;
        p=L->next;//p points back to the letter A
    }
    for(auto a:mmWem_)
    {
        cout<<"Ciphertext:"<<a.miwen<<" "<<"Key:"<<a.mishi;
        cout<<endl;
    }
    char c;
    cout<<"Press 0 to exit!!!"<<endl;
    cout<<"Enter plaintext:"<<endl;
    while(1)
    {
        cin>>c;
        if(c=='0')
        {
            break;
        }
        else
        {
            int m=c-'A';//Serial number corresponding to plaintext

            for(int i=0;i<m;i++)//Location of plaintext found
            {
                p=p->next;
            }
            cout<<"Plaintext"<<p->data<<" "<<"Ciphertext:"<<mmWem_[m].miwen<<" "<<"Key:"<<mmWem_[m].mishi;
            p=L->next;
        }
        cout<<endl;
        cout<<endl;
        cout<<"Press 0 to exit!!!"<<endl;
        cout<<"Enter plaintext:"<<endl;
    }
}

int main() {


    int choice=1;
    while(choice)
    {
        cout<<endl;
        cout<<"Please enter 1 to select an alphabet output question"<<endl;
        cout<<"choice Vingenre Encryption problem, please enter 2"<<endl;
        cout<<"Exit, please enter 0"<<endl;
        cin>>choice;
        switch (choice) {
            case 1 :
                alpha_cout();
                break;
            case 2 :
                Vingenre();
                break;
            case 0 :
                exit(0);
                break;
        }
    }
    return 0;
}

Stack and queue

Definition of stack


Press push three times

Click pop

Sequential storage structure of stack




Stack operation


Out of stack operation


There is no data at the top of the stack. It is ready to store data.






Empty stack

Destroy stack


example







The code is as follows:

#include <iostream>
#include <math.h>
using namespace std;
#define STACK_INIT_SIZE 20
#define STACKINCREMENT 10
typedef char ElemType;
typedef struct {
    ElemType *base;
    ElemType *top;
    int stackSize;
}sqStack;

/**
 * Create a stack
 * @param s
 */
void initStack(sqStack *s)
{
    s->base=(ElemType *) malloc(STACK_INIT_SIZE*sizeof (ElemType));
    if(!s->base)
    {
        exit(0);
    }
    s->top=s->base;
    s->stackSize=STACK_INIT_SIZE;
}

/**
 * Push 
 * @return
 */
void Push(sqStack *s,ElemType e)
{
    //If the stack is full, expand the space
    if(s->top-s->base>=s->stackSize)
    {
        s->base=(ElemType *) realloc(s->base,(s->stackSize+STACKINCREMENT)*sizeof (ElemType));//realloc is to create a space on the right and copy it to the left
        if(!s->base)
        {
            exit(0);
        }
        s->top= s->base+s->stackSize;//Position of stack top
        s->stackSize=s->stackSize+STACKINCREMENT;//Reset stack capacity

    }
    *(s->top)=e;
    s->top++;
}

/**
 * Out of stack
 * @return
 */
 void pop(sqStack *s,ElemType *e)
{
     if(s->top==s->base)
     {
         return ;
     }
     *e=*--(s->top);//Because top shows off that it does not store data, it is used to prepare to store the next data
}

/**
 * Stack size
 */
int StackLen(sqStack s)
{
    return (s.top-s.base);
}

/**
 * empty
 * @return
 */
 void ClearStack(sqStack *s)
{
     s->top=s->base;
}

/**
 * Destroy stack
 * @return
 */
 void DestroyStack(sqStack *s)
 {
     int i,len;
     len=s->stackSize;
     for(i=0;i<len;i++)
     {
         free(s->base);
         s->base++;
     }
     s->base=s->top=NULL;
     s->stackSize=0;
 }

 /**
  * Binary conversion decimal
  * @return
  */
  void TwoToTen()
{
    ElemType c;
    sqStack s;
    initStack(&s);
    int len ,i,sum=0;

    cout<<"Please enter binary number#The symbol indicates the end! "<<endl;
    cin>>c;
    while(c!='#'/ / don't use' / n 'because the Assic of / n is 10. If you enter one, you need to press the newline character, and the newline will also be pushed as input
    {
        Push(&s,c);
        cin>>c;
    }
    getchar();//After all are accepted, the keyboard will accept an Assic of '/ n' / n, which is 10. Therefore, to filter out this 10, use getchar() to get '/ n';

    len= StackLen(s);
    cout<<"Current capacity of stack:"<<len<<endl;
    for(i=0;i<len;i++)
    {
        pop(&s,&c);
        sum=sum+(c-48)*pow(2,i);
    }

    cout<<"Convert to decimal: "<<sum<<endl;
}

/**
 * Binary conversion octal only needs to build another stack and calculate octal with a three cycle
 * @return
 */


int main() {
    TwoToTen();
    return 0;
}

Chain storage structure of stack



Stacking of chain stack

Out of chain stack

practice






Inverse Polish calculator



At present, there is a problem with the code running on your own computer. It is implemented the same as the code of little turtle, but I don't know what went wrong.
Found the problem. It's a problem with input statements. You can't use cin, because cin automatically ignores spaces. Fuck!
Reference blog

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <ctype.h>
    using namespace std;
#define STACK_INIT_SIZE 20
#define STACKINCREMENT 10
#define MAXBUFFER 10
    typedef float ElemType;
    typedef struct {
        ElemType *base;
        ElemType *top;
        int stackSize;
    }sqStack;

/**
 * Create a stack
 * @param s
 */
    void initStack(sqStack *s)
    {
        s->base=(ElemType *) malloc(STACK_INIT_SIZE*sizeof (ElemType));
        if(!s->base)
        {
            exit(0);
        }
        s->top=s->base;
        s->stackSize=STACK_INIT_SIZE;
    }

/**
 * Push 
 * @return
 */
    void Push(sqStack *s,ElemType e)
    {
        //If the stack is full, expand the space
        if(s->top-s->base>=s->stackSize)
        {
            s->base=(ElemType *) realloc(s->base,(s->stackSize+STACKINCREMENT)*sizeof (ElemType));//realloc is to create a space on the right and copy it to the left
            if(!s->base)
            {
                exit(0);
            }
            s->top= s->base+s->stackSize;//Position of stack top
            s->stackSize=s->stackSize+STACKINCREMENT;//Reset stack capacity

        }
        *(s->top)=e;
        s->top++;
    }

/**
 * Out of stack
 * @return
 */
    void Pop(sqStack *s,ElemType *e)
    {
        if(s->top==s->base)
        {
            return ;
        }
        *e=* --(s->top);//Because top does not store data, it is used to prepare to store the next data
    }

/**
 * Stack size
 */
    int StackLen(sqStack s)
    {
        return (s.top-s.base);
    }

/**
 * empty
 * @return
 */
    void ClearStack(sqStack *s)
    {
        s->top=s->base;
    }

/**
 * Destroy stack
 * @return
 */
    void DestroyStack(sqStack *s)
    {
        int i,len;
        len=s->stackSize;
        for(i=0;i<len;i++)
        {
            free(s->base);
            s->base++;
        }
        s->base=s->top=NULL;
        s->stackSize=0;
    }

    /**
     * Polish calculator
     */

  

int main() {
   sqStack s;

   char c;
   int i=0;
   float d,e;
   char str[MAXBUFFER];
    initStack(&s);
   cout<<"Please press the inverse Polish expression to enter data with calculation. The data and operators are separated by spaces to#As an end flag: "< < endl;
   cin>>c;
   while(c != '#')
    {
        while(isdigit(c) || c=='.')//Used to filter numbers
        {
            str[i++]=c;
            str[i]='\0';
            if(i>=10)
            {
                cout<<"Error: the single data entered is too large!"<<endl;
                return -1;
            }
            cin>>c;
            if(c==' ')
            {
                d=atof(str);//Convert to double
                Push(&s,d);
                i=0;
                break;
            }
        }

        switch(c)
        {
            case '+':
                Pop(&s,&e);//Note that the data in the Stack here is double
                Pop(&s,&d);
                Push(&s,d+e);
                break;
            case '-':
                Pop(&s,&e);//Note that the data in the Stack here is double
                Pop(&s,&d);
                Push(&s,d-e);
                break;
            case '*':
                Pop(&s,&e);//Note that the data in the Stack here is double
                Pop(&s,&d);
                Push(&s,d*e);
                break;
            case '/':
                Pop(&s,&e);//Note that the data in the Stack here is double
                Pop(&s,&d);
                if(e!=0)
                {
                    Push(&s,d/e);
                }
                else
                {
                    cout<<"Error: divisor is zero!"<<endl;
                    return -1;
                }
                break;
        }
        cin>>c;
    }
    Pop(&s,&d);
   cout<<"Final calculation results:"<<d<<endl;
    return 0;
}

Here is the correct code:

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
#define STACK_INIT_SIZE 20
#define STACKINCREMENT  10
#define MAXBUFFER       10

typedef double ElemType;
typedef struct
{
    ElemType *base;
    ElemType *top;
    int stackSize;
}sqStack;

void InitStack(sqStack *s)
{
    s->base = (ElemType *)malloc(STACK_INIT_SIZE * sizeof(ElemType));
    if( !s->base )
        exit(0);

    s->top = s->base;
    s->stackSize = STACK_INIT_SIZE;
}

void Push(sqStack *s, ElemType e)
{
// Stack full, additional space, fish oil must understand!
    if( s->top - s->base >= s->stackSize )
    {
        s->base = (ElemType *)realloc(s->base, (s->stackSize + STACKINCREMENT) * sizeof(ElemType));
        if( !s->base )
            exit(0);

        s->top = s->base + s->stackSize;
        s->stackSize = s->stackSize + STACKINCREMENT;
    }

    *(s->top) = e;      // Store data
    s->top++;
}

void Pop(sqStack *s, ElemType *e)
{
    if( s->top == s->base )
        return;

    *e = *--(s->top);   // Pop up the stack top element and modify the stack top pointer
}

int StackLen(sqStack s)
{
    return (s.top - s.base);
}

int main()
{
    sqStack s;
    char c;
    double d, e;
    char str[MAXBUFFER];
    int i = 0;

    InitStack( &s );

    printf("Please enter the data to be calculated according to the inverse Polish expression. The data and operator are separated by spaces to#As an end flag: \ n "");
    scanf("%c", &c);
//cin>>c ;
    while( c != '#' )
    {
        while( isdigit(c) || c=='.' )  // Used to filter numbers
        {
            str[i++] = c;
            str[i] = '\0';
            if( i >= 10 )
            {
                printf("Error: the single data entered is too large!\n");
                return -1;
            }
            scanf("%c", &c);
           //cin>>c ;
           if( c == ' ' )
            {
                d = atof(str);
                Push(&s, d);
                i = 0;
                break;
            }
        }

        switch( c )
        {
            case '+':
                Pop(&s, &e);
                Pop(&s, &d);
                Push(&s, d+e);
                break;
            case '-':
                Pop(&s, &e);
                Pop(&s, &d);
                Push(&s, d-e);
                break;
            case '*':
                Pop(&s, &e);
                Pop(&s, &d);
                Push(&s, d*e);
                break;
            case '/':
                Pop(&s, &e);
                Pop(&s, &d);
                if( e != 0 )
                {
                    Push(&s, d/e);
                }
                else
                {
                    printf("\n Error: divisor is zero!\n");
                    return -1;
                }
                break;
        }

        scanf("%c", &c);
        //cin>>c;
    }

    Pop(&s, &d);
    printf("\n The final calculation result is:%f\n", d);

    return 0;
}

// 5 - (6 + 7) * 8 + 9 / 4
// 5 - 13 * 8 + 9 / 4
// 5 - 104 + 2.25
// -99 + 2.25
// 5 6 7 + 8 * - 9 4 / +

Infix expression becomes suffix expression












The complete code of infix expression to suffix expression + inverse Polish calculator is as follows:

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <iostream>
#include <string>
using namespace std;

/**
 * Convert infix expression to suffix expression
 */
namespace mToL
{


#define STACK_INIT_SIZE 20
#define STACKINCREMENT  10
#define MAXBUFFER       10
    typedef char ElemType;
    typedef struct
    {
        ElemType *base;
        ElemType *top;
        int stackSize;
    }sqStack;

    void InitStack(sqStack *s)
    {
        s->base = (ElemType *)malloc(STACK_INIT_SIZE * sizeof(ElemType));
        if( !s->base )
            exit(0);

        s->top = s->base;
        s->stackSize = STACK_INIT_SIZE;
    }

    void Push(sqStack *s, ElemType e)
    {
// Stack full, additional space, fish oil must understand!
        if( s->top - s->base >= s->stackSize )
        {
            s->base = (ElemType *)realloc(s->base, (s->stackSize + STACKINCREMENT) * sizeof(ElemType));
            if( !s->base )
                exit(0);

            s->top = s->base + s->stackSize;
            s->stackSize = s->stackSize + STACKINCREMENT;
        }

        *(s->top) = e;      // Store data
        s->top++;
    }

    void Pop(sqStack *s, ElemType *e)
    {
        if( s->top == s->base )
            return;

        *e = *--(s->top);   // Pop up the stack top element and modify the stack top pointer
    }

    int StackLen(sqStack s)
    {
        return (s.top - s.base);
    }

/**
 * Convert infix expression to suffix expression
 */
    string mToL_test()
    {
        //Convert infix expression to suffix expression
        sqStack s;
        InitStack( &s );
        string str;
        printf("Please enter infix expression to#As an end flag: ";
        char c;
        char e;
        scanf("%c",&c);
        while(c!='#')
        {
            while(isdigit(c) )
            {
                printf("%c", c);
                str+=c;
                scanf("%c", &c);
                if(!isdigit(c) )//
                {
                    printf(" ");
                    str+=' ';
                }
            }

            if(')'==c)
            {
                Pop(&s,&e);//
                while('('!=e)
                {
                    printf("%c ", e);//The output character is followed by a space
                    str+=e;
                    str+=' ';
                    Pop(&s,&e);//
                }
            }
            else if('+'==c||'-'==c)
            {
                if(!StackLen(s))//If stack is empty
                {
                    Push(&s,c);
                }
                else
                {
                    do
                    {
                        Pop(&s,&e);
                        if('('== e)//First judge whether there is an open parenthesis. If so, it means that c must be included in the parenthesis. Therefore, the left parenthesis should be placed in it until the right parenthesis is is used to match the operator in the pop-up parenthesis
                        {
                            Push(&s,e);//
                        }
                        else//If it is not the left bracket, it will pop up directly, such as 9 + 3 + (1 + 3) --- 9 3 - 1 3+
                        {
                            printf("%c ", e);//The output character is followed by a space
                            str+=e;
                            str+=' ';
                        }
                    }
                    while(StackLen(s) && '('!=e);//
                    Push(&s,c);
                }
            }
            else if('*'==c|| '/'==c ||'('==c)
            {
                Push(&s,c);
            }
            else if( '#'== c )
            {
                break;
            }
            else
            {
                cout<<"Input format error!"<<endl;
                //return -1;
            }

            scanf("%c",&c);
        }
        while( StackLen(s) )
        {
            Pop(&s, &e);
            printf("%c ", e);
            str+=e;
            str+=' ';
            //printf("%c ", e);
        }

        return str+'#';

    }
}
/**
 * Inverse Polish calculator
 */
namespace PolanCaulatuer
{


#define STACK_INIT_SIZE 20
#define STACKINCREMENT  10
#define MAXBUFFER       10
    typedef double ElemType;
    typedef struct
    {
        ElemType *base;
        ElemType *top;
        int stackSize;
    }sqStack;

    void InitStack(sqStack *s)
    {
        s->base = (ElemType *)malloc(STACK_INIT_SIZE * sizeof(ElemType));
        if( !s->base )
            exit(0);

        s->top = s->base;
        s->stackSize = STACK_INIT_SIZE;
    }

    void Push(sqStack *s, ElemType e)
    {
// Stack full, additional space, fish oil must understand!
        if( s->top - s->base >= s->stackSize )
        {
            s->base = (ElemType *)realloc(s->base, (s->stackSize + STACKINCREMENT) * sizeof(ElemType));
            if( !s->base )
                exit(0);

            s->top = s->base + s->stackSize;
            s->stackSize = s->stackSize + STACKINCREMENT;
        }

        *(s->top) = e;      // Store data
        s->top++;
    }

    void Pop(sqStack *s, ElemType *e)
    {
        if( s->top == s->base )
            return;

        *e = *--(s->top);   // Pop up the stack top element and modify the stack top pointer
    }

    int StackLen(sqStack s)
    {
        return (s.top - s.base);
    }
    /**
 * Polish inverse calculator
 */
void PolanCaulauter(string strl)
{
    sqStack s;
    char c;
    double d, e;
    char str[MAXBUFFER];
    int i = 0;
    int j = 0;
    InitStack( &s );

    //printf("please input the data to be calculated according to the inverse Polish expression, and separate the data from the operator with a space to # serve as the end flag: \ n");

    //scanf("%c", &c);
    //cin>>c ;
        c=strl[0];

        cout<<"size: "<<strl.size()<<endl;

            while( c != '#')
            {
                while( isdigit(c) || c=='.' )  // Used to filter numbers
                {
                    str[i++] = c;
                    str[i] = '\0';
                    if( i >= 10 )
                    {
                        printf("Error: the single data entered is too large!\n");
                        //return -1;
                    }
                    c=strl[++j];
                    //scanf("%c", &c);
                    //cin>>c ;
                    if( c == ' ' )
                    {
                        d = atof(str);
                        Push(&s, d);
                        i = 0;
                        break;
                    }

                }

                switch( c )
                {
                    case '+':
                        Pop(&s, &e);
                        Pop(&s, &d);
                        Push(&s, d+e);
                        break;
                    case '-':
                        Pop(&s, &e);
                        Pop(&s, &d);
                        Push(&s, d-e);
                        break;
                    case '*':
                        Pop(&s, &e);
                        Pop(&s, &d);
                        Push(&s, d*e);
                        break;
                    case '/':
                        Pop(&s, &e);
                        Pop(&s, &d);
                        if( e != 0 )
                        {
                            Push(&s, d/e);
                        }
                        else
                        {
                            printf("\n Error: divisor is zero!\n");
                            //return -1;
                        }
                        break;
                    default:
                        break;
                }
                c=strl[++j];
                //scanf("%c", &c);
                //cin>>c;
            }

    Pop(&s, &d);
    printf("\n The final calculation result is:%f\n", d);

    // 5 - (6 + 7) * 8 + 9 / 4
// 5 - 13 * 8 + 9 / 4
// 5 - 104 + 2.25
// -99 + 2.25
// 5 6 7 + 8 * - 9 4 / +
}

}

int main()
{
    string s;
    s=mToL::mToL_test();
    cout<<endl;
    cout<<s<<endl;
    PolanCaulatuer::PolanCaulauter(s);

    return 0;
}


Queue queue



Create a queue

Queued operation

Out of queue operation



Destroy a queue

#include <iostream>

using namespace std;
typedef char ElemType;
typedef struct QNode
{
    ElemType data;
    struct QNode *next;
}QNode,*QueuePtr ;
typedef struct {
    QueuePtr front,rear;//Point to the header and tail nodes, and the header does not store data
}LinkQueue;

/**
 * Initialize queue
 * @param q
 */
void initQueue(LinkQueue *q)
{
    q->front=q->rear=(QueuePtr) malloc(sizeof (QNode));
    if(!q->front)
    {
        exit(0);
        q->front->next=NULL;
    }
}

/**
 * Enter queue
 * @param q
 * @param e
 */
void InsertQueue(LinkQueue *q,ElemType e)
{
    QueuePtr p;
    p=(QueuePtr) malloc(sizeof (QNode));
    p->data=e;
    p->next=NULL;
    q->rear->next=p;
    q->rear=p;
}

/**
 * Out of queue
 * @param q
 * @param e
 */
void DeleteQueue(LinkQueue *q,ElemType *e)
{
    QueuePtr p;
    if(q->front==q->rear)//Empty queue
        return;
    p=q->front->next;
    *e=p->data;
    q->front->next=p->next;
    if(q->rear==p)//There is only one element
    {
        q->rear=q->front;
    }
    free(p);
}

/**
 * Destroy queue
 * @param q
 */
void DestoryQueue(LinkQueue *q)
{
    while(q->front)
    {
        q->rear=q->front->next;//Point to the next node after each node to be destroyed
        free(q->front);
        q->front=q->rear;//Move the first node back

    }
}

int main() {
    ElemType c;
    LinkQueue q;
    initQueue(&q);
    cout<<"Please enter a string to#No. end input. "<<endl;
    scanf("%c", &c);
    while('#'!=c)
    {
        InsertQueue( &q, c );
        scanf("%c", &c);
    }
    cout<<"Elements in the print queue:"<<endl;
    while(q.front!=q.rear)
    {
        DeleteQueue( &q, &c );
        cout<<c;
    }
    cout<<endl;
    return 0;
}

Sequential storage of queues



Circular queue







Define circular queue

Initialize circular queue

Queued operation



#include <iostream>
using namespace std;
#define MAXSIZE 100
typedef int ElemType;

typedef struct cycleQueue
{
    ElemType *base;
    int front;
    int rear;//Indicates where it can be used
}cycleQueue;

/**
 * Initialize circular queue
 * @param q
 */
void initLoopQueue(cycleQueue *q)
{
    q->base=( ElemType *) malloc(MAXSIZE*sizeof (ElemType));
    if(!q->base)
    {
        exit(0);
    }
    q->front=q->rear=0;
}

/**
 * Queue
 * @param q
 * @param e
 */
void InsertQueue(cycleQueue *q,ElemType e)
{
    if((q->rear+1)%MAXSIZE==q->front)
    {
        return;//The queue is full
    }
    q->base[q->front]=e;
    q->rear=(q->rear+1)%MAXSIZE;
}

/**
 * Out of queue
 * @param q
 * @param e
 */
void DeleteQueue(cycleQueue *q,ElemType *e)
{
    if(q->front==q->rear)
    {
        return;//Queue empty
    }
    *e=q->base[q->front];
    q->front=(q->front+1)%MAXSIZE;
}

int main() {
    std::cout << "Hello, World!" << std::endl;
    return 0;
}

Recursion and divide and conquer


Recursive implementation of Fibonacci sequence





#include <iostream>
using namespace std;

void iter()
{
    int a[40];
    a[0]=0;
    a[1]=1;
    cout<<a[0]<<" ";
    cout<<a[1]<<" ";
    for(int i=2;i<40;i++)
    {
        a[i]=a[i-1]+a[i-2];
        cout<<a[i]<<" ";
    }
}

int DiGui_Fib(int n)
{
    if(n<2)
    {
        return n==0?0:1;
    }
    else
    {
        return DiGui_Fib(n-1)+ DiGui_Fib(n-2);
    }
}

int main() {

    iter();
    int a =DiGui_Fib(39);
    cout<<a<<endl;
    return 0;
}

Recursive definition



example



void DiGui_StrInverse()
{
    char c;
    scanf("%c",&c);
    if('#'!=c) DiGui_StrInverse();
    if('#'!=c) cout<<c;
}

Partition thought


Recursive implementation of half search method


#include <iostream>
using namespace std;

void iter()
{
    int a[40];
    a[0]=0;
    a[1]=1;
    cout<<a[0]<<" ";
    cout<<a[1]<<" ";
    for(int i=2;i<40;i++)
    {
        a[i]=a[i-1]+a[i-2];
        cout<<a[i]<<" ";
    }
}

int DiGui_Fib(int n)
{
    if(n<2)
    {
        return n==0?0:1;
    }
    else
    {
        return DiGui_Fib(n-1)+ DiGui_Fib(n-2);
    }
}

void DiGui_StrInverse()
{
    char c;
    scanf("%c",&c);
    if('#'!=c) DiGui_StrInverse();
    if('#'!=c) cout<<c;
}

/**
 * Binary recursive search
 * @param str 
 * @param low 
 * @param high 
 * @param k 
 * @return 
 */
int binary_Search_DiGui(int str[],int low,int high,int k)
{
    if(low>high)
    {
        return -1;
    }
    else
    {
        int  mid = (low+high)/2;
        if(str[mid]==k)
        {
            return mid;
        }
        if(str[mid]<k)
        {
            return binary_Search_DiGui(str,mid+1,high,k);
        }
        else
        {
            return binary_Search_DiGui(str,low,mid-1,k);
        }
    }


}
int main() {

    
    /*iter();Fibonacci sequence iteration
    int a =DiGui_Fib(39);//Fibonacci sequence recursion
    cout<<a<<endl;*/

    //DiGui_StrInverse();

//Binary search recursion
    int str[11] = {1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89};
    int n, addr;
    printf("Please enter the keyword to be found: ");
    scanf("%d", &n);
    addr= binary_Search_DiGui(str,0,10,n);
    if( -1 != addr )
    {
        printf("Find success, Congratulations, Coca Cola! keyword %d The location is: %d\n", n, addr);
    }
    else
    {
        printf("Search failed!\n");
    }

    return 0;
}

Hanoi







#include <iostream>
using namespace std;

void iter()
{
    int a[40];
    a[0]=0;
    a[1]=1;
    cout<<a[0]<<" ";
    cout<<a[1]<<" ";
    for(int i=2;i<40;i++)
    {
        a[i]=a[i-1]+a[i-2];
        cout<<a[i]<<" ";
    }
}

int DiGui_Fib(int n)
{
    if(n<2)
    {
        return n==0?0:1;
    }
    else
    {
        return DiGui_Fib(n-1)+ DiGui_Fib(n-2);
    }
}

/**
 *
 */
 void Febonaci_test()
{
    iter();
int a =DiGui_Fib(39);//Fibonacci sequence recursion
cout<<a<<endl;


}

/**
 *
 */
void DiGui_StrInverse()
{
    char c;
    scanf("%c",&c);
    if('#'!=c) DiGui_StrInverse();
    if('#'!=c) cout<<c;
}



/**
 * Binary recursive search
 * @param str
 * @param low
 * @param high
 * @param k
 * @return
 */
int binary_Search_DiGui(int str[],int low,int high,int k)
{
    if(low>high)
    {
        return -1;
    }
    else
    {
        int  mid = (low+high)/2;
        if(str[mid]==k)
        {
            return mid;
        }
        if(str[mid]<k)
        {
            return binary_Search_DiGui(str,mid+1,high,k);
        }
        else
        {
            return binary_Search_DiGui(str,low,mid-1,k);
        }
    }


}

void binary_Search_DiGui_test()
{
    //Binary search recursion
    int str[11] = {1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89};
    int n, addr;
    printf("Please enter the keyword to be found: ");
    scanf("%d", &n);
    addr= binary_Search_DiGui(str,0,10,n);
    if( -1 != addr )
    {
        printf("Find success, Congratulations, Coca Cola! keyword %d The location is: %d\n", n, addr);
    }
    else
    {
        printf("Search failed!\n");
    }

}

/**
 * Move n plates from x to z by means of y
 * @param n
 * @param x
 * @param y
 * @param z
 */
void move(int n,char x,char y,char z)
{
    if(1==n)
    {
        cout<<x<<"-->"<<z<<" ";
    }
    else
    {
        move(n-1,x,z,y);//First move the first n-1 from x to y by means of z
        cout<<x<<"-->"<<z<<" ";//Then move the bottom nth to z
        move(n-1,y,x,z);//Finally, move the n-1 plates on y to z with the help of x
    }
}

/**
 * Hanoi 
 */
void HanNuoTa()
{
    cout<<"Please enter the number of floors of Hanoi Tower:"<<endl;
    int n;
    cin>>n;
    cout<<"The moving steps are as follows:"<<endl;
    move(n,'X','Y','Z');
}
int main() {

    HanNuoTa();
    return 0;
}

//Taking the three-story Hanoi tower as an example, the recursive process is as follows:
3 x y z
{
2 x z y
	{
		1 x y z 	x-->z
		x-->y
		1 z x y		z-->y
	}
	x-->z
2 y x z
	{
		1 y z x 	y-->x
		y-->z
		1 x y z 	x-->z
	}
}



//The final result is:
x-->z
x-->y
z-->y
x-->z
y-->x
y-->z
x-->z

No matter how many layers, in essence, it can recurse to 1, then return to 2, and then return to n-1 again.

Eight queens problem

#include <iostream>
using namespace std;

int count=0;//Count the number of eight queens
/**
 * Judge whether there is a queen at the slash position of [row,j]
 * @param row
 * @param j
 * @param chess
 * @return
 */
int notDanger(int row,int j,int (*chess)[8])
{
    int i,k,flag1=0,flag2=0,flag3=0,flag4=0,flag5=0;
    //Judge whether there is danger in all directions
    // Determine column direction
    for( i=0; i < 8; i++ )
    {
        if( *(*(chess+i)+j) != 0 )
        {
            flag1 = 1;
            break;
        }
    }

    //Judge upper left
    for(i=row,k=j;i>=0&&k>=0;i--,k--)
    {
        if( *(*(chess+i)+k) != 0 )
        {
            flag2 = 1;
            break;
        }
    }
    // Judge lower right
    for( i=row, k=j; i<8 && k<8; i++, k++ )
    {
        if( *(*(chess+i)+k) != 0 )
        {
            flag3 = 1;
            break;
        }
    }

    // Judge upper right
    for( i=row, k=j; i>=0 && k<8; i--, k++ )
    {
        if( *(*(chess+i)+k) != 0 )
        {
            flag4 = 1;
            break;
        }
    }

    // Judge lower left
    for( i=row, k=j; i<8 && k>=0; i++, k-- )
    {
        if( *(*(chess+i)+k) != 0 )
        {
            flag5 = 1;
            break;
        }
    }

    if(flag1 || flag2 || flag3 || flag4 || flag5)
    {
        return 0;
    }
    else
    {

        return 1;
    }

}
/**
 * Eight queens recursive implementation, in fact, a good understanding is to use recursion to automatically traverse each line
 * @param row  Represents the starting line
 * @param n Indicates the number of columns
 * @param chess Pointer to each line of the chessboard
 */
 void EightQueen(int row,int n,int (*chess)[8])//chess points to each row
{
    int chess2[8][8],i,j;
    //Assign chess2 the value of chessboard chess
    for(i=0;i<8;i++)
    {
        for(j=0;j<8;j++)
        {
            chess2[i][j]=chess[i][j];
        }
    }
    if(row==8)
    {
        cout<<"The first"<<count+1<<"species"<<endl;
        for(i=0;i<8;i++)
        {
            for(j=0;j<8;j++)
            {
               cout<<*(*(chess2+i)+j);
            }
            cout<<endl;
        }
        cout<<endl;
        count++;
    }
    else
    {
        //Judge whether this position is dangerous
        //If there is no danger, go on

        for(j=0;j<n;j++)
        {
            if(notDanger(row,j,chess)) //Judge whether this position is dangerous
            {
                for(i=0;i<8;i++)
                {
                    *(*(chess2+row)+i)=0;//Mark the entire column as 0 first
                }
                *(*(chess2+row)+j)=1;//Then mark the non dangerous position as 1 -- that is, the position of the queen
                EightQueen(row+1,n,chess2);
            }
        }
    }
};

 void EightQueen_test()
 {
     int chess[8][8];
     for(int i=0;i<8;i++)
     {
         for(int j=0;j<8;j++)
         {
             chess[i][j]=0;//Initialize chessboard
         }
     }
     EightQueen(0,8,chess);

 }
int main()
{
	EightQueen_test();
	return 0;
}

Here is the complete recursive divide and conquer Code:

#include <iostream>
using namespace std;

void iter()
{
    int a[40];
    a[0]=0;
    a[1]=1;
    cout<<a[0]<<" ";
    cout<<a[1]<<" ";
    for(int i=2;i<40;i++)
    {
        a[i]=a[i-1]+a[i-2];
        cout<<a[i]<<" ";
    }
}

int DiGui_Fib(int n)
{
    if(n<2)
    {
        return n==0?0:1;
    }
    else
    {
        return DiGui_Fib(n-1)+ DiGui_Fib(n-2);
    }
}

/**
 *
 */
 void Febonaci_test()
{
    iter();
int a =DiGui_Fib(39);//Fibonacci sequence recursion
cout<<a<<endl;


}

/**
 *
 */
void DiGui_StrInverse()
{
    char c;
    scanf("%c",&c);
    if('#'!=c) DiGui_StrInverse();
    if('#'!=c) cout<<c;
}



/**
 * Binary recursive search
 * @param str
 * @param low
 * @param high
 * @param k
 * @return
 */
int binary_Search_DiGui(int str[],int low,int high,int k)
{
    if(low>high)
    {
        return -1;
    }
    else
    {
        int  mid = (low+high)/2;
        if(str[mid]==k)
        {
            return mid;
        }
        if(str[mid]<k)
        {
            return binary_Search_DiGui(str,mid+1,high,k);
        }
        else
        {
            return binary_Search_DiGui(str,low,mid-1,k);
        }
    }


}

void binary_Search_DiGui_test()
{
    //Binary search recursion
    int str[11] = {1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89};
    int n, addr;
    printf("Please enter the keyword to be found: ");
    scanf("%d", &n);
    addr= binary_Search_DiGui(str,0,10,n);
    if( -1 != addr )
    {
        printf("Find success, Congratulations, Coca Cola! keyword %d The location is: %d\n", n, addr);
    }
    else
    {
        printf("Search failed!\n");
    }

}

/**
 * Move n plates from x to z by means of y
 * @param n
 * @param x
 * @param y
 * @param z
 */
void move(int n,char x,char y,char z)
{
    if(1==n)
    {
        cout<<x<<"-->"<<z<<" ";
    }
    else
    {
        move(n-1,x,z,y);//First move the first n-1 from x to y by means of z
        cout<<x<<"-->"<<z<<" ";//Then move the bottom nth to z
        move(n-1,y,x,z);//Finally, move the n-1 plates on y to z with the help of x
    }
}

/**
 * Hanoi 
 */
void HanNuoTa()
{
    cout<<"Please enter the number of floors of Hanoi Tower:"<<endl;
    int n;
    cin>>n;
    cout<<"The moving steps are as follows:"<<endl;
    move(n,'X','Y','Z');
}

int count=0;//Count the number of eight queens
/**
 * Judge whether there is a queen at the slash position of [row,j]
 * @param row
 * @param j
 * @param chess
 * @return
 */
int notDanger(int row,int j,int (*chess)[8])
{
    int i,k,flag1=0,flag2=0,flag3=0,flag4=0,flag5=0;
    //Judge whether there is danger in all directions
    // Determine column direction
    for( i=0; i < 8; i++ )
    {
        if( *(*(chess+i)+j) != 0 )
        {
            flag1 = 1;
            break;
        }
    }

    //Judge upper left
    for(i=row,k=j;i>=0&&k>=0;i--,k--)
    {
        if( *(*(chess+i)+k) != 0 )
        {
            flag2 = 1;
            break;
        }
    }
    // Judge lower right
    for( i=row, k=j; i<8 && k<8; i++, k++ )
    {
        if( *(*(chess+i)+k) != 0 )
        {
            flag3 = 1;
            break;
        }
    }

    // Judge upper right
    for( i=row, k=j; i>=0 && k<8; i--, k++ )
    {
        if( *(*(chess+i)+k) != 0 )
        {
            flag4 = 1;
            break;
        }
    }

    // Judge lower left
    for( i=row, k=j; i<8 && k>=0; i++, k-- )
    {
        if( *(*(chess+i)+k) != 0 )
        {
            flag5 = 1;
            break;
        }
    }

    if(flag1 || flag2 || flag3 || flag4 || flag5)
    {
        return 0;
    }
    else
    {

        return 1;
    }

}
/**
 * Eight queens recursive implementation, in fact, a good understanding is to use recursion to automatically traverse each line
 * @param row  Represents the starting line
 * @param n Indicates the number of columns
 * @param chess Pointer to each line of the chessboard
 */
 void EightQueen(int row,int n,int (*chess)[8])//chess points to each row
{
    int chess2[8][8],i,j;
    //Assign chess2 the value of chessboard chess
    for(i=0;i<8;i++)
    {
        for(j=0;j<8;j++)
        {
            chess2[i][j]=chess[i][j];
        }
    }
    if(row==8)
    {
        cout<<"The first"<<count+1<<"species"<<endl;
        for(i=0;i<8;i++)
        {
            for(j=0;j<8;j++)
            {
               cout<<*(*(chess2+i)+j);
            }
            cout<<endl;
        }
        cout<<endl;
        count++;
    }
    else
    {
        //Judge whether this position is dangerous
        //If there is no danger, go on

        for(j=0;j<n;j++)
        {
            if(notDanger(row,j,chess)) //Judge whether this position is dangerous
            {
                for(i=0;i<8;i++)
                {
                    *(*(chess2+row)+i)=0;//Mark the entire column as 0 first
                }
                *(*(chess2+row)+j)=1;//Then mark the non dangerous position as 1 -- that is, the position of the queen
                EightQueen(row+1,n,chess2);
            }
        }
    }
};

 void EightQueen_test()
 {
     int chess[8][8];
     for(int i=0;i<8;i++)
     {
         for(int j=0;j<8;j++)
         {
             chess[i][j]=0;//Initialize chessboard
         }
     }
     EightQueen(0,8,chess);

 }


int main() {

    //HanNuoTa();
    EightQueen_test();




    return 0;
}
/*Taking the three-story Hanoi tower as an example, the recursive process is as follows:
3 x y z
{
2 x z y
{
1 x y z 	x-->z
        x-->y
1 z x y		z-->y
}
x-->z
2 y x z
{
1 y z x 	y-->x
        y-->z
1 x y z 	x-->z
}
}



The final result is:
        x-->z
        x-->y
        z-->y
        x-->z
        y-->x
        y-->z
        x-->z
        */

character string




Storage structure of string

BF algorithm


#include <iostream>
#include <string>
using namespace std;
//Violence algorithm classic shape, judge the size of two strings
int compare_Eaual(string &s1,string &s2)
{
    int flag=0;
    int n1=s1.size();
    int n2=s2.size();
    n1=max(n1,n2);
        for(int i=0;i<n1;i++)
        {

                 if(s1[i]>s2[i])
                 {
                     flag=1;
                     break;
                 }
                 else if(s1[i]==s2[i])
                 {
                     flag=0;
                 }
                 else if(s1[i]<s2[i])
                 {
                     flag=-1;
                     break;
                 }
        }


    return flag;


}

int main() {
    string s1="aaf";
    string s2="abf";
    int jue;
    jue=compare_Eaual(s1,s2);
    if(jue==1)
    {
        cout<<"s1>s2"<<endl;
    }
    else if(jue==0)
    {
        cout<<"s1=s2"<<endl;
    }
    else if(jue==-1)
    {
        cout<<"s1<s2"<<endl;
    }
    return 0;
}

KMP algorithm






No backtracking is required i

When determining the inequality, there is no same character in front of the pattern string, and the backtracking starts from 1

There are two equal characters in the pattern string, and the backtracking starts from 2


There is a pair of equal characters in the pattern string, and the backtracking starts from 2





When the matching is unequal, the prefix and suffix of the string formed from the beginning A to the previous position of the matching inequality have several equal characters. Add n equal characters, then j starts from the position of n+1. (Prefix suffix is not A string in position)

Analysis of NEXT array code principle of KMP algorithm

The NEXT array is the K above

void get_next(string T,int *next)
{
    int j=0;
    int i=1;

    next[1]=0;
    while(i<T[0])//When the suffix exceeds the length, the matching is completed
    {
        if(j==0||  T[i]==T[j])
        {
            i++;
            j++;
            next[i]=j;
        }
        else
        {
            //j backtracking
            j=next[j];

        }

//Because the prefix is fixed, the suffix is relative (the prefix is the actual character)
    }
}

//Returns the position of string T after the pos character of main string S
//If it does not exist, 0 is returned
int Index_KMP(string S,string T,int pos)
{
    int i=pos;
    int j=1;
    int next[255];
    get_next(T,next);//Get next array
    while(i<=S[0]&&j<=T[0])//S[0] and T[0] store the length of the string
    {
        if(j==0|| S[i]==T[j])
        {
            i++;
            j++;
        }
        else
        {
            j=next[j];//The soul of KMP algorithm uses next as the highest guide
        }

    }
    //After successful matching, j must be one bit larger than the string of T
    if(j>T[0])
    {
        return i-T[0];
    }
    else
    {
        return 0;
    }
}

Implementation and optimization of KMP algorithm



What about this special case
In this way, when it is judged that the position is not equal, if the position is m, then when the character of T in position m-1 and the prefix character are equal, j will directly return to the position corresponding to the prefix, which is back to 0 in the above figure

#include <iostream>
#include <string>
using namespace std;

void get_next(string T,int *next)
{
    int j=0;
    int i=1;

    next[1]=0;
    while(i<T[0])//When the suffix exceeds the length, the matching is completed
    {
        if(j==0||  T[i]==T[j])
        {
            i++;
            j++;
            //improvement
            if(T[i]!=T[j])
            {
                next[i]=j;
            }
            else
            {
                next[i]=next[j];//Assign prefix
            }

        }
        else
        {
            //j backtracking
            j=next[j];

        }

//Because the prefix is fixed, the suffix is relative (the prefix is the actual character)
    }
}

//Returns the position of string T after the pos character of main string S
//If it does not exist, 0 is returned
int Index_KMP(string S,string T,int pos)
{
    int i=pos;
    int j=1;
    int next[255];
    get_next(T,next);//Get next array
    while(i<=S[0]&&j<=T[0])//S[0] and T[0] store the length of the string
    {
        if(j==0|| S[i]==T[j])
        {
            i++;
            j++;
        }
        else
        {
            j=next[j];//The soul of KMP algorithm uses next as the highest guide
        }

    }
    //After successful matching, j must be one bit larger than the string of T
    if(j>T[0])
    {
        return i-T[0];
    }
    else
    {
        return 0;
    }
}

int main() {

char str[255]=" aaaaax";
int next[255];
int i=1;
str[0]=9;
    get_next(str,next);
    for(i=1;i<10;i++)
    {
        cout<<next[i]<<" ";
    }





    return 0;
}

tree





In the figure above, the largest node of the whole tree is 3


The depth of the tree above is 3 because it has three layers.

Storage structure of tree


// Definition of node structure of parent representation of tree
#define MAX_TREE_SIZE 100

typedef int ElemType;

typedef struct PTNode
{
	ElemType data;	// Node data
	int parent;		// Parental position
}PTNode;

typedef struct
{
	PTNode nodes[MAX_TREE_SIZE];
	int r;			// Location of root
	int n;			// Number of nodes
}PTree;

Parental representation


A is a root without parents, so it is - 1

Child representation






The one on the left is an array, and the one on the right is linked with a chain

#define MAX_TREE_SIZE 100
typedef char ElemType;
//Child node
typedef struct  CTNode
{
    int child;//Subscript to child node
    struct  CTNode *next;//Pointer to the next child node

}* Childptr;

//Header structure
typedef struct
{
    ElemType data; //Data stored in nodes of tree species
    int parent;//Location of parents
    Childptr firstchild;//Pointer to the first child
}CTBox;

//Tree structure
typedef struct
{
    CTBox nodes[MAX_TREE_SIZE];//Node array
    int r;//Location of root
    int n;//Number of nodes in the tree
};

Binary tree



Pay attention to distinguish between left subtree and right subtree
Five mentality of binary tree



Oblique trees can only lean all to the left or all to the right.





The above figure is still a complete binary tree, but not a full binary tree.
Because the serial numbers above are still connected, 1 2 3 4 5

The above features are reflected in the figure above
None of the following is a complete binary tree



The above three are just ordinary binary trees

Properties of binary tree




Round up and down.





It's too theoretical. Just have a look. It's not interesting.
Storage structure of binary tree




This is a waste of resources.

Traversal of binary tree







It's easy to remember the concept of big family and small family


Establishment and traversal algorithm of binary tree


#include <iostream>
#include <stdlib.h>
#include <stdio.h>
using namespace std;

typedef char ElemType;

typedef struct BiTNode
{
    char data;
    struct BiTNode *lchild,*rchild;
}BiTNode ,*BiTree;


//Create a binary tree
/**
 * The user enters the left and right root in the way of preorder traversal
 * @param *T It's a pointer
 */
void CreatBiTree(BiTree *T)
{
    char c;
    scanf("%c",&c);
    if(' '==c)//Develop good code writing habits
    {
        *T=NULL;//If the character is a space, let this point to a null pointer
    }
    else
    {
        *T= (BiTNode *)malloc(sizeof (BiTNode));//(BiTNode *) force to a pointer of type BiTNode
        (*T)->data=c;
        CreatBiTree(&(*T)->lchild);
        CreatBiTree(&(*T)->rchild);
    }
}

//Specific operations for accessing binary tree nodes
void visit(char c,int level)
{
    cout<<c<<"In the first"<<level<<"layer"<<endl;
}
//Traversal binary tree
void PreOrderTraverse(BiTree T,int level)
{
    if(T)
    {
        //If the root is traversed in middle order, just change the position
        visit(T->data,level);
        PreOrderTraverse(T->lchild,level+1);
        PreOrderTraverse(T->rchild,level+1);
    }
}

//The input method is AB space D space CE space
void test_PreTravese()
{
    int level=1;
    BiTree  T=NULL;
    CreatBiTree(&T);
    PreOrderTraverse(T,level);
}

int main() {


    test_PreTravese();

    return 0;
}

Clue binary tree




Using middle order seems to solve this problem
Because the discovery is a law separated one by one

The front drive is represented by a black curved arrow
The following is indicated by a red straight arrow





This program is difficult to understand. It is recommended to debug.

#include <iostream>
#include <stdlib.h>
#include <stdio.h>

using namespace std;
typedef char ElemType;

//Thread store flag bit enumeration
//Link(0) indicates the pointer to the left and right children
//Thread(1) indicates a clue to the predecessor and successor
typedef enum{Link,Thread} PointerTag;
typedef struct BiThrNode
{
    ElemType data;
    struct BiThrNode *lchild,*rchild;
    PointerTag ltag;
    PointerTag rtag;

}BiThrNode,*BithrTree;

//The global variable always points to the node you just accessed
BithrTree pre;



//Create a binary tree and agree that users enter data by traversing in the previous order
/**
 *
 * @param *T It's a pointer
 */
void CreatBiTree(BithrTree *T)
{
    char c;
    scanf("%c",&c);
    if(' '==c)//Develop good code writing habits
    {
        *T=NULL;//If the character is a space, let this point to a null pointer
    }
    else
    {
        *T= (BiThrNode *)malloc(sizeof (BiThrNode));//(BiTNode *) force to a pointer of type BiTNode
        (*T)->data=c;
        //First set it to have left and right children
        (*T)->ltag=Link;
        (*T)->rtag=Link;
        CreatBiTree(&(*T)->lchild);
        CreatBiTree(&(*T)->rchild);
    }
}

//Middle order traversal cueing
void InThreading(BithrTree T)
{
    if(T)
    {
        InThreading(T->lchild);//Recursive left child cueing is to go to the leftmost one first, and the leftmost one will point to the following statement
        //Node processing
        if(!T->lchild)//If the node has no left child, set ltag to Thread and point lchild to the node just accessed
        {
            T->ltag=Thread;
            T->lchild=pre;
        }
        if(!pre->rchild)
        {
            pre->rtag=Thread;
            pre->rchild=T;
        }
        pre=T;
        InThreading(T->rchild);//Recursive right child cueing
    }
};

 void visit(char c)
 {
    cout<<c<<endl;
 }

//Middle order traversal binary tree iteration
//T here should be the header pointer pre
void InorderTravse(BithrTree T)
{
    BithrTree p;
    p=T->lchild;
    while(p!=T)
    {
        while(p->ltag==Link)//Find the lowest left node
        {
            p=p->lchild;
        }
        visit(p->data);

        while(p->rtag==Thread && p->rchild!=T)
        {
            p=p->rchild;
            visit(p->data);
        }
        p=p->rchild;//Point back to the head node
    }
}


void InorderThreading(BithrTree *p,BithrTree T)
{
    *p=(BiThrNode *)malloc(sizeof (BiThrNode));
    (*p)->ltag=Link;
    (*p)->rtag=Thread;
    (*p)->rchild=*p;
    if(!T)
    {
        (*p)->lchild=*p;
    }
    else
    {
        (*p)->lchild=T;
        pre=*p;
        InThreading(T);
        //After the recursion, pre points to f and performs the following actions to point the left child of C to F
        pre->rchild=*p;
        pre->rtag=Thread;
        (*p)->rchild=pre;
    }

}

int main() {
    BithrTree  p,T=NULL;
    CreatBiTree(&T);
    InorderThreading(&p,T);
    cout<<"The output result of middle order traversal is:"<<endl;
    InorderTravse(p);
    return 0;
}


Transformation of trees, forests and binary trees












Traversal of trees and forests



huffman tree



People with 70-90 scores need to make three judgments to know (this score segment accounts for the largest proportion). The efficiency is a little low


Corresponding data of the left tree
 To node c For example:
C Path length: 3
 Path length of tree: 1+2+3+3
C Weighted path length: 70*3
 Weighted path length of tree WPL: 1*5+15*2+70*3+10*3

Corresponding data of the right tree
 Weighted path length of tree WPL: 1*10+2*70+3*15+3*5

Obviously, the weighted path length of the right tree WPL Less than the weighted path length of the left tree WPL,So the tree on the right is more efficient.








Huffman coding




Some data structures in the code

//Queue node
typedef struct _pQueueNode {
	TYPE val;//Point to tree node
	unsigned int priority;//The number of occurrences of characters, that is, the weight of Huffman coding
	struct _pQueueNode *next;//Node pointing to the next queue
}pQueueNode;

// pQueue is the head of the queue
typedef struct _pQueue {
	unsigned int size; //The length of the storage queue. The last one is the root node of the tree
	pQueueNode *first; //Point to the first node of the queue
}pQueue;

//Huffman tree node
typedef struct _htNode {
	char symbol;//Store character
	struct _htNode *left, *right;//Left subtree right subtree
}htNode;

//The Huffman table nodes (linked list implementation)
typedef struct _hlNode {
	char symbol; //Store characters such as a
	char *code;//Store the Huffman code corresponding to character a, for example, 0010
	struct _hlNode *next; //Point to next_ hlNode
}hlNode;

//Incapsularea listei
typedef struct _hlTable {
	hlNode *first;//Point to first_ hlNode
	hlNode *last;//Point to last_ hlNode
}hlTable;

The code is as follows:
pQueue.h

#pragma once / / prevent duplicate definition of header file
#ifndef _PQUEUE_H
#define _PQUEUE_H

#include "huffman.h"

//We modify the data type to hold pointers to Huffman tree nodes
#define TYPE htNode *

#define MAX_SZ 256

//Queue node
typedef struct _pQueueNode {
	TYPE val;//Point to tree node
	unsigned int priority;//The number of occurrences of characters, that is, the weight of Huffman coding
	struct _pQueueNode *next;//Node pointing to the next queue
}pQueueNode;

// pQueue is the head of the queue
typedef struct _pQueue {
	unsigned int size; //The length of the storage queue. The last one is the root node of the tree
	pQueueNode *first; //Point to the first node of the queue
}pQueue;

void initPQueue(pQueue **queue);
void addPQueue(pQueue **queue, TYPE val, unsigned int priority);
TYPE getPQueue(pQueue **queue);

#endif

huffman.h

#pragma once
#ifndef _HUFFMAN_H
#define _HUFFMAN_H

//The Huffman tree node definition
//Huffman tree node
typedef struct _htNode {
	char symbol;//Store character
	struct _htNode *left, *right;//Left subtree right subtree
}htNode;

/*
	We "encapsulate" the entire tree in a structure
	because in the future we might add fields like "size"
	if we need to. This way we don't have to modify the entire
	source code.
*/
typedef struct _htTree {
	htNode *root;
}htTree;

//The Huffman table nodes (linked list implementation)
typedef struct _hlNode {
	char symbol; //Store characters such as a
	char *code;//Store the Huffman code corresponding to character a, for example, 0010
	struct _hlNode *next; //Point to next_ hlNode
}hlNode;

//Incapsularea listei
typedef struct _hlTable {
	hlNode *first;//Point to first_ hlNode
	hlNode *last;//Point to last_ hlNode
}hlTable;

htTree * buildTree(char *inputString);
hlTable * buildTable(htTree *huffmanTree);
void encode(hlTable *table, char *stringToEncode);
void decode(htTree *tree, char *stringToDecode);

#endif

pQueue.cpp

#include "pQueue.h"
#include <stdlib.h>
#include <stdio.h>

/**
 * Initialize queue
 * @param queue  Pointer to column header
 */
void initPQueue(pQueue **queue)
{
	//We allocate memory for the priority queue type
	//and we initialize the values of the fields
	(*queue) = (pQueue *) malloc(sizeof(pQueue));//(* queue) is equivalent to huffmanQueue generating space for the header pointer
	(*queue)->first = NULL;
	(*queue)->size = 0;
	return;
}
/**
 * Join queue
 * @param queue  Header pointer of the queue
 * @param val    Node of tree
 * @param priority  Number of occurrences of characters
 */
void addPQueue(pQueue **queue, TYPE val, unsigned int priority)
{
	//If the queue is full we don't have to add the specified value.
	//We output an error message to the console and return.
	if((*queue)->size == MAX_SZ)//The queue is full
	{
		printf("\nQueue is full.\n");
		return;
	}

	//The queue is not full
	pQueueNode *aux = (pQueueNode *)malloc(sizeof(pQueueNode));//The node to which a queue is assigned
	aux->priority = priority;//Number of character occurrences
	aux->val = val;//Pointer to the node of the tree

	//If the queue is empty we add the first value.
	//We validate twice in case the structure was modified abnormally at runtime (rarely happens).
	if((*queue)->size == 0 || (*queue)->first == NULL) //When the queue is empty, just throw things directly into it
	{
		aux->next = NULL;
		(*queue)->first = aux;
		(*queue)->size = 1;
		return;
	}
	else//If it is not empty, it is inserted into the queue according to the law of increasing the number of characters
	{
		//If there are already elements in the queue and the priority of the element
		//that we want to add is greater than the priority of the first element,
		//we'll add it in front of the first element.

		//Be careful, here we need the priorities to be in descending order
		if(priority<=(*queue)->first->priority)//For example, if character a appears once and character b appears once, put the node of the queue with b in front of A
		{
			aux->next = (*queue)->first;//
			(*queue)->first = aux;
			(*queue)->size++;
			return;
		}
		else
		{
			//We're looking for a place to fit the element depending on it's priority
			pQueueNode * iterator = (*queue)->first;//iterator 
			while(iterator->next!=NULL)//Traverse the node according to the loop, so that the node is inserted into the queue according to the number of character occurrences (increasing)
			{
				//Same as before, descending, we place the element at the begining of the
				//sequence with the same priority for efficiency even if
				//it defeats the idea of a queue.
				if(priority<=iterator->next->priority)
				{
					aux->next = iterator->next;
					iterator->next = aux;
					(*queue)->size++;
					return;
				}
				iterator = iterator->next;
			}
			//If we reached the end and we haven't added the element,
			//we'll add it at the end of the queue.
			if(iterator->next == NULL)//If there is only one node in the queue and the number of characters in this node is less than that in the current node, the current node will be directly followed
			{
					aux->next = NULL;
					iterator->next = aux;
					(*queue)->size++;
					return;
			}
		}
	}
}


//Get data from the queue. The generation of Huffman tree is to obtain the priority of two tree nodes, and then add them together to generate a new tree node. The left child and the right child are the two tree nodes respectively
/**
 * Obtain the corresponding tree node of the queue. After obtaining one, the first node pointed to by the queue head will move back
 * @param queue  Queue header pointer
 * @return TYPE Pointer to tree node
 */
TYPE getPQueue(pQueue **queue)
{
	TYPE returnValue;
	//We get elements from the queue as long as it isn't empty
	if((*queue)->size>0)
	{
		returnValue = (*queue)->first->val;
		(*queue)->first = (*queue)->first->next;//Here, change the first node of the queue pointed to by the header pointer
		(*queue)->size--;
	}
	else
	{
		//If the queue is empty we show an error message.
		//The function will return whatever is in the memory at that time as returnValue.
		//Or you can define an error value depeding on what you choose to store in the queue.
		printf("\nQueue is empty.\n");
	}
	return returnValue;
}

huffman.cpp

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "huffman.h"
#include "pQueue.h"

/**
 *
 * @param treeNode Throw in the node of the Huffman tree
 * @param table    Huffman table to be filled
 * @param k        Layers of Huffman tree
 * @param code     Huffman code --- fill in according to the rules of left subtree 0 and right subtree 1
 */
void traverseTree(htNode *treeNode, hlTable **table, int k, char code[256])
{
	//If we reach the end we introduce the code in the table
	if(treeNode->left == NULL && treeNode->right == NULL)//At the bottom, treeNode is a leaf
	                                                     //The characters in the Huffman tree are placed on the leaves
	{
		code[k] = '\0';//End of string
		hlNode *aux = (hlNode *)malloc(sizeof(hlNode));
		aux->code = (char *)malloc(sizeof(char)*(strlen(code)+1));
		strcpy(aux->code,code);
		aux->symbol = treeNode->symbol;
		aux->next = NULL;
		//The following is a simple operation
		if((*table)->first == NULL)
		{
			(*table)->first = aux;
			(*table)->last = aux;
		}
		else
		{
		    //Similar tail insertion
			(*table)->last->next = aux;
			(*table)->last = aux;
		}
		
	}
	//We use recursion to realize traversal
	//We concatenate a 0 for each step to the left
	if(treeNode->left!=NULL)
	{
		code[k]='0';
		traverseTree(treeNode->left,table,k+1,code);
		
	}
	//We concatenate a 1 for each step to the right
	if(treeNode->right!=NULL)
	{
		code[k]='1';
		traverseTree(treeNode->right,table,k+1,code);
		
	}
}

/**
 * Generate Huffman table
 * @param huffmanTree
 * @return
 */
hlTable * buildTable(htTree * huffmanTree)
{
	//We initialize the table
	hlTable *table = (hlTable *)malloc(sizeof(hlTable));
	table->first = NULL;
	table->last = NULL;
	
	//Auxiliary variables
	char code[256];
	//k will memories the level on which the traversal is
	int k=0;

	//We traverse the tree and calculate the codes
	traverseTree(huffmanTree->root,&table,k,code);//The nodes passed into the Huffman tree and the table to be filled,
	                                              // k stands for the layer,
	                                              // Code to store the code. If you leave the left subtree, add '0' and if you leave the right subtree, add '1'‘
	return table;
}

/**
 * Generating Huffman tree
 * @param inputString---character string
 * @return Root node of Huffman tree
 */
htTree * buildTree(char *inputString)
{
	//The array in which we calculate the frequency of the symbols
	//Knowing that there are only 256 posibilities of combining 8 bits
	//(256 ASCII characters)
	int * probability = (int *)malloc(sizeof(int)*256);

	//initialization
	//We initialize the array
	for(int i=0; i<256; i++)
		probability[i]=0;

	//Count the number of occurrences of each character of the string to be encoded
	//We consider the symbol as an array index and we calculate how many times each symbol appears
	for(int i=0; inputString[i]!='\0'; i++)
		probability[(unsigned char) inputString[i]]++;//For example, if the first character is I and its ASCII is 73, this is probability[73] + +;

	//The queue which will hold the tree nodes
	//pQueue queue header node
	pQueue * huffmanQueue;
	initPQueue(&huffmanQueue);//Initialization--

	//Fill queue
	//We create nodes for each symbol in the string
	for(int i=0; i<256; i++)
		if(probability[i]!=0)//This character has appeared
		{
			htNode *aux = (htNode *)malloc(sizeof(htNode));//Assign a tree node
			aux->left = NULL;
			aux->right = NULL;
			aux->symbol = (char) i;//i represents the ASCII value of the character, (char) i becomes the corresponding character and passes this character to the tree node
			
			addPQueue(&huffmanQueue,aux,probability[i]);//Join this queue
		}

	//We free the array because we don't need it anymore
	free(probability);//When the probability runs out, the heap space is released

	//Generating Huffman tree
	//We apply the steps described in the article to build the tree
	while(huffmanQueue->size!=1)//Equal to 1 means that only the root node is left
	{
		int priority = huffmanQueue->first->priority;
		priority+=huffmanQueue->first->next->priority;//Add up the number of occurrences of the first two characters, that is, the number of new nodes, where the number is actually the weight of Huffman coding

		htNode *left = getPQueue(&huffmanQueue);//After the left subtree is obtained once each time, the header pointer automatically points to the next queue node to be obtained
		htNode *right = getPQueue(&huffmanQueue);//Right subtree

		//Generate a new tree node
		htNode *newNode = (htNode *)malloc(sizeof(htNode));
		newNode->left = left;
		newNode->right = right;

		addPQueue(&huffmanQueue,newNode,priority);//According to the law of increasing times, check the new tree node into the queue
	}

	//Establish the root node of Huffman tree
	//We create the tree
	htTree *tree = (htTree *) malloc(sizeof(htTree));

	//At this point, getpqueue (& huffmanqueue) gets the last node in the column and assigns it to the Huffman tree root node of the tree
	tree->root = getPQueue(&huffmanQueue);
	
	return tree;
}

/**
 * code
 * Output the Huffman encoding of the Input string
 * @param table Huffman table
 * @param stringToEncode The string you want to encode -- Input -- the file to be compressed
 */
void encode(hlTable *table, char *stringToEncode)
{
	hlNode *traversal;//Traversal Huffman table
	
	printf("\nEncoding\nInput string : %s\nEncoded string : \n",stringToEncode);

	//For each element of the string traverse the table
	//and once we find the symbol we output the code for it
	for(int i=0; stringToEncode[i]!='\0'; i++)
	{
		traversal = table->first;
		while(traversal->symbol != stringToEncode[i])//while is used to find the Huffman table node of the corresponding character
			traversal = traversal->next;
		printf("%s",traversal->code);
	}

	printf("\n");
}

/**
 * decode
 * In fact, it is to traverse the Huffman tree. 0 is to go to the left and 1 is to the right
 * @param tree huffman tree 
 * @param stringToDecode  Huffman code to be decoded - Input
 */
void decode(htTree *tree, char *stringToDecode)
{
	htNode *traversal = tree->root;//First point to the root node of Huffman tree

	printf("\nDecoding\nInput string : %s\nDecoded string : \n",stringToDecode);

	//For each "bit" of the string to decode
	//we take a step to the left for 0
	//or ont to the right for 1
	for(int i=0; stringToDecode[i]!='\0'; i++)
	{
		if(traversal->left == NULL && traversal->right == NULL)//I got the leaves
		{
			printf("%c",traversal->symbol);//Output character
			traversal = tree->root;//Back to the root node
		}
		
		if(stringToDecode[i] == '0')
			traversal = traversal->left;

		if(stringToDecode[i] == '1')
			traversal = traversal->right;

		if(stringToDecode[i]!='0'&&stringToDecode[i]!='1')
		{
			printf("The input string is not coded correctly!\n");
			return;
		}
	}

	//The Huffman code to be decoded has been traversed here
	if(traversal->left == NULL && traversal->right == NULL)
	{
		printf("%c",traversal->symbol);//Output character
		traversal = tree->root;//Back to the root node
	}

	printf("\n");
}

main.cpp

#include <stdio.h>
#include <stdlib.h>
#include "huffman.h"

int main(void)
{
	//We build the tree depending on the string
	htTree *codeTree = buildTree("beep boop beer!");//build Huffman tree
	//We build the table depending on the Huffman tree
	hlTable *codeTable = buildTable(codeTree);//Huffman table, which stores the encoding of each character

	//We encode using the Huffman table
	encode(codeTable,"beep boop beer!");//code
	//We decode using the Huffman tree
	//We can decode string that only use symbols from the initial string
	decode(codeTree,"0011111000111");//decode
	//Output : 0011 1110 1011 0001 0010 1010 1100 1111 1000 1001
	return 0;
}

chart


Many to many relationship



The order of vi vj in disordered pairs











A digraph adds the word "strong"

Adding two edges is not a spanning tree


This is not a spanning tree either, because it is two subgraphs

The directed graph on the left becomes the forest on the right. The forest on the right is composed of two directed trees.

Storage structure of graph

Because it is an undirected graph, the two-dimensional array is symmetrical.

adjacency matrix

Adjacency matrix code definition of undirected graph and directed graph

// The time complexity is O(n+n^2+e)

#define MAXVEX 100 			//  max vertex 
#define INFINITY 65535 		//  65535 is used to represent infinity

typedef struct
{
	char vexs[MAXVEX];				// Vertex table
	int arc[MAXVEX][MAXVEX];		// adjacency matrix 
	int numVertexes, numEdges;		// The current number of vertices and edges in the graph
} MGraph;



char flag;

// The adjacency matrix of undirected network graph is established
void CreateMGraph(MGraph *G)
{
	int i, j, k, w;
	int flag;
    printf("Please enter whether to generate undirected or directed, undirected input 0, directed input 1:\n");
    cin>>flag;
	printf("Please enter the number of vertices and edges:\n");
	scanf("%d %d", &G->numVertexes, &G->numEdges);
	
	for( i=0; i < G->numVertexes; i++ )
	{
		scanf("%c", &G->vexs[i]);
	}
	
	for( i=0; i < G->numVertexes; i++ )
	{
		for( j=0; j < G->numVertexes; j++ )
		{
			G->arc[i][j] = INFINITY;			// Adjacency matrix initialization
		}
	}

	if(flag==0)
    {
        for( k=0; k < G->numEdges; k++ )
        {
            printf("Please enter an edge(Vi,Vj)Subscript on i,subscript j And corresponding rights w:\n");		// This is just an example. Improving the user experience needs to be improved
            scanf("%d %d %d", &i, &j, &w);
            G->arc[i][j] = w;
            G->arc[j][i] = G->arc[i][j];			// Is an undirected net graph, symmetric matrix
        }
    }
	else
    {
        for( k=0; k < G->numEdges; k++ )
        {
            printf("Please enter an edge(Vi,Vj)Subscript on i,subscript j And corresponding rights w:\n");		// This is just an example. Improving the user experience needs to be improved
            scanf("%d %d %d", &i, &j, &w);
            G->arc[i][j] = w;

        }
    }

}

Adjacency table

#define MAXVEX 100
    //Edge table node
    typedef struct EdgeTNode
    {
        int vertx;//adjacent vertex 
        int weight;//weight
        EdgeTNode *next;//
    }EdgeTNode;

    //Vertex table node
    typedef struct VertxTNode
    {
        char data;          			//Vertex domain vertex information
        EdgeTNode *firstedge;		        // Point to the first adjacent node
    }VertxTNode ,Vertx[MAXVEX];

    //Overall diagram
    typedef struct
    {
        Vertx vertx_;
        int numVertexes, numEdges;		// The current number of vertices and edges in the graph

    }Graph_LinJieT;



    //establish
    void CreatLinJie(Graph_LinJieT *G)
    {
        int i,j ,k;
        EdgeTNode *e;
        printf("Please enter the number of vertices and edges:\n");
        scanf("%d %d", &G->numVertexes, &G->numEdges);

        for( i=0;i<G->numVertexes;i++)
        {
            G->vertx_[i].firstedge=NULL;//initialization
        }

        for(k=0;k<G->numEdges;k++)
        {
            //The header insertion used here is the opposite of the adjacency table in the figure, but it also achieves the goal in the end
            printf("Please enter an edge(Vi,Vj)Vertex sequence number on:\n");
            scanf("%d %d", &i, &j);
            //i is adjacent to j on the left
            e = (EdgeTNode *)malloc(sizeof(EdgeTNode));
            e->vertx=j;
            e->next=G->vertx_[i].firstedge;//For example, input (0, 1) 1 will point to NULL
            G->vertx_[i].firstedge=e;
            
            //If it is an undirected graph, you have to execute the following statement
            //j is adjacent on the left, and the serial number is i
            e = (EdgeTNode *)malloc(sizeof(EdgeTNode));
            e->vertx=i;
            e->next=G->vertx_[j].firstedge;//For example, input (0, 1) 1 will point to NULL
            G->vertx_[j].firstedge=e;
            
        }
        
    }


//Textbook answer:
#define MAXVEX 100

typedef struct EdgeNode			// Edge table node
{
	int adjvex;					// The adjacent point field stores the subscript corresponding to the vertex
	int weight;					// It is used to store weights. It is not required for non network graphs
	struct EdgeNode *next;		// Chain domain, pointing to the next adjacent node
} EdgeNode;

typedef struct VertexNode		// Vertex table node
{
	char data;					// Vertex domain, storing vertex information
	EdgeNode *firstEdge;		// Edge header pointer
} VertexNode, AdjList[MAXVEX];

typedef struct
{
	AdjList adjList;
	int numVertexes, numEdges;	// The current number of vertices and edges in the graph
} GraphAdjList;

// Establish the adjacency table structure of graph
void CreateALGraph(GraphAdjList *G)
{
	int i, j, k;
	EdgeNode *e;
	
	printf("Please enter the number of vertices and edges:\n");
	scanf("%d %d", &G->numVertexes, &G->numEdges);
	
	// Read vertex information and establish vertex table
	for( i=0; i < G->numVertexes; i++ )
	{
		scanf("%c", &G->adjList[i].data);
		G->adjList[i].firstEdge = NULL;		// Initialization set to empty table
	}

	//This is an undirected graph
	for( k=0; k < G->numEdges; k++ )
	{
		printf("Please enter an edge(Vi,Vj)Vertex sequence number on:\n");
		scanf("%d %d", &i, &j);
		
		e = (EdgeNode *)malloc(sizeof(EdgeNode));
		e->adjvex = j;						// Adjacency serial number is j
		e->next = G->adjList[i].firstEdge;
		G->adjList[i].firstEdge = e;
		
		e = (EdgeNode *)malloc(sizeof(EdgeNode));
		e->adjvex = i;						// Adjacency serial number is i
		e->next = G->adjList[j].firstEdge;
		G->adjList[j].firstEdge = e;
	}
}

Orthogonal list

First, the adjacency table has out degree and the inverse adjacency table has in degree. The two add up to a cross linked list

Blue stands for out adjacency table

Red stands for read in - inverse adjacency table

Adjacency multiple table

Edge set array

Freud's Iceberg Theory

Graph traversal - depth first traversal DFS

If the point to the right of a point has passed, retreat to the previous point

The walking route is shown in the following figure:

The blue one is accessible, the red one is visited, and can't go.

Depth traversal of adjacency matrix

The following code is based on the structure of adjacency matrix for depth traversal

#include <iostream>

using namespace std;
#define MAXVEX 100 			//  max vertex 
#define INFINITY 65535 		//  65535 is used to represent infinity

typedef struct
{
    char vexs[MAXVEX];				// Vertex table
    int arc[MAXVEX][MAXVEX];		// adjacency matrix 
    int numVertexes, numEdges;		// The current number of vertices and edges in the graph
} MGraph;

// The adjacency matrix of undirected network graph is established
void CreateMGraph(MGraph *G)
{
    int i, j, k, w;
    int flag;
    printf("Please enter whether to generate undirected or directed, undirected input 0, directed input 1:\n");
    cin>>flag;
    printf("Please enter the number of vertices and edges:\n");
    scanf("%d %d", &G->numVertexes, &G->numEdges);

    for( i=0; i < G->numVertexes; i++ )
    {
        scanf("%c", &G->vexs[i]);
    }

    for( i=0; i < G->numVertexes; i++ )
    {
        for( j=0; j < G->numVertexes; j++ )
        {
            G->arc[i][j] = INFINITY;			// Adjacency matrix initialization
        }
    }

    if(flag==0)//Undirected
    {
        for( k=0; k < G->numEdges; k++ )
        {
            printf("Please enter an edge(Vi,Vj)Subscript on i,subscript j And corresponding rights w:\n");		// This is just an example. Improving the user experience needs to be improved
            scanf("%d %d %d", &i, &j, &w);
            G->arc[i][j] = w;
            G->arc[j][i] = G->arc[i][j];			// Is an undirected net graph, symmetric matrix
        }
    }
    else//Directed
    {
        for( k=0; k < G->numEdges; k++ )
        {
            printf("Please enter an edge(Vi,Vj)Subscript on i,subscript j And corresponding rights w:\n");		// This is just an example. Improving the user experience needs to be improved
            scanf("%d %d %d", &i, &j, &w);
            G->arc[i][j] = w;

        }
    }

}

#define TRUE 1
#define FALSE 0
#define MAX 256

typedef int Boolean;	// Here, we define Boolean as boolean type, and its value is TRUE or FALSE
Boolean visited[MAX];	// Array of access flags

void DFS(MGraph G,int i)
{
    visited[i]=true;//Vertex i has been accessed
    cout<<G.vexs[i]<<endl;//Output visited vertices
    for(int j=0;j<G.numVertexes;j++)
    {
        if(G.arc[i][j]==1 && !visited[j])//Vertex i forms an edge with vertex j, and vertex j has not been accessed
        {
            DFS(G,j);//recursion
        }
    }
}

Adjacency table depth traversal

The following code performs depth traversal in the structure of adjacency table

#include <iostream>
using namespace std;

#define MAXVEX 100

typedef struct EdgeNode			// Edge table node
{
    int adjvex;					// The adjacent point field stores the subscript corresponding to the vertex
    int weight;					// It is used to store weights. It is not required for non network graphs
    struct EdgeNode *next;		// Chain domain, pointing to the next adjacent node
} EdgeNode;

typedef struct VertexNode		// Vertex table node
{
    char data;					// Vertex domain, storing vertex information
    EdgeNode *firstEdge;		// Edge header pointer
} VertexNode, AdjList[MAXVEX];

typedef struct
{
    AdjList adjList;
    int numVertexes, numEdges;	// The current number of vertices and edges in the graph
} GraphAdjList;

// Establish the adjacency table structure of graph
void CreateALGraph(GraphAdjList *G)
{
    int i, j, k;
    EdgeNode *e;

    printf("Please enter the number of vertices and edges:\n");
    scanf("%d %d", &G->numVertexes, &G->numEdges);

    // Read vertex information and establish vertex table
    for( i=0; i < G->numVertexes; i++ )
    {
        scanf("%c", &G->adjList[i].data);
        G->adjList[i].firstEdge = NULL;		// Initialization set to empty table
    }

    //This is an undirected graph
    for( k=0; k < G->numEdges; k++ )
    {
        printf("Please enter an edge(Vi,Vj)Vertex sequence number on:\n");
        scanf("%d %d", &i, &j);

        //Head insertion
        e = (EdgeNode *)malloc(sizeof(EdgeNode));
        e->adjvex = j;						// Adjacency serial number is j
        e->next = G->adjList[i].firstEdge;
        G->adjList[i].firstEdge = e;

        e = (EdgeNode *)malloc(sizeof(EdgeNode));
        e->adjvex = i;						// Adjacency serial number is i
        e->next = G->adjList[j].firstEdge;
        G->adjList[j].firstEdge = e;
    }
}


#define TRUE 1
#define FALSE 0
#define MAX 256
typedef int Boolean;	// Here, we define Boolean as boolean type, and its value is TRUE or FALSE
Boolean visited[MAX];	// Array of access flags


//Depth traversal we traverse with the rules of adjacency table
void DFS(GraphAdjList GL,int  i)
{
    EdgeNode *e;
    visited[i]= true;//Indicates that you have visited

    cout<<GL.adjList[i].data<<endl;//Output visited vertices
    //This loop traverses the edges adjacent to vertex i
    while(e)
    {
        if(!visited[e->adjvex]);
        {
            DFS(GL,e->adjvex);
        }
        e=e->next;//e points to the next vertex adjacent to i
    }
}


void DFSTraverse(GraphAdjList GL)
{
    for(int i=0;i<GL.numVertexes;i++)
    {
        visited[i]=FALSE;//All default to 0
    }

    //Traverse all vertices
    for(int i=0;i<GL.numVertexes;i++)
    {
        if(!visited[i])// Initializing all vertex States is an unreachable state. You can proceed only if you have not accessed them
        {
            DFS(GL,i); If it is a connected graph, it will be executed only once, and this point has not been accessed
        }
    }
}

knight's tour

#include <iostream>
#include <ctime>
#include "stdio.h"

using namespace std;

//Chessboard 8 x 8
#define X 8
#define Y 8

//checkerboard
int chess[X][Y];

/**
 * The next walkable case based on finding the (x,y) position
 * @param x
 * @param y
 * @param count
 * @return
 */
int nextxy(int *x,int *y,int count)
{

    //Eight walking methods
    switch (count)
    {
        case 0:
            if(*x+2<=X-1 && *y-1>=0 &&chess[*x+2][*y-1]==0)//Jump to the right. You should judge the position of 3 within the chessboard range, and this position has not been traversed
            {
                *x = *x + 2;
                *y = *y - 1;
                return 1;
            }
            break;

        case 1:
            if(*x+2<=X-1 && *y+1<=Y-1 &&chess[*x+2][*y+1]==0) //The judgment is 4 this position
            {
                *x = *x + 2;
                *y = *y + 1;
                return 1;
            }
            break;
        case 2:
            if(*x+1<=X-1 && *y-2>=0 &&chess[*x+1][*y-2]==0) //The judgment is 2 this position
            {
                *x = *x + 1;
                *y = *y - 2;
                return 1;
            }
            break;
        case 3:
            if(*x+1<=X-1 && *y+2<=Y-1 &&chess[*x+1][*y+2]==0) //The judgment is 5 this position
            {
                *x = *x + 1;
                *y = *y + 2;
                return 1;
            }
            break;
        case 4:
            if(*x-2>=0 && *y-1>=0 &&chess[*x-2][*y-1]==0) //The judgment is 8 this position
            {
                *x = *x - 2;
                *y = *y - 1;
                return 1;
            }
            break;
        case 5:
            if(*x-2>=0 && *y+1<=Y-1 && chess[*x-2][*y+1]==0) //The judgment is 7 this position
            {
                *x = *x - 2;
                *y = *y + 1;
                return 1;
            }
            break;
        case 6:
            if(*x-1>=0 && *y-2>=0 && chess[*x-1][*y-2]==0) //The position of 1 is judged
            {
                *x = *x - 1;
                *y = *y - 2;
                return 1;
            }
            break;
        case 7:
            if(*x-1>=0 && *y+2<=Y-1 &&chess[*x-1][*y+2]==0) //The judgment is 6 this position
            {
                *x = *x - 1;
                *y = *y + 2;
                return 1;
            }
            break;
        default:
            break;
    }
    return 0;
}

/**
 * Print chessboard
 */
void print()
{
    int i,j;
    for(i=0;i<X;i++)
    {
        for(j=0;j<Y;j++)
        {
            printf("%2d\t", chess[i][j]);
        }
        cout<<endl;
    }
    cout<< endl;
}

/**
 * Depth first traversal chessboard
 * (x,y)Is the starting position
 * @param x
 * @param y
 * @param tag Tag variable tag+1 every step
 * @return
 */
int TravelChessBoard(int x,int y,int tag)
{
    int x1=x,y1=y,flag=0,count=0;
    chess[x][y]=tag;
    if(tag == X*Y)
    {
        //Print chessboard
        print();
        return 1;
    }

        //Find the next walking coordinate (x1,y1) of the horse. If flag=1 is found, otherwise it is 0

        flag= nextxy(&x1,&y1,count);//Find the next feasible location
        //The while here is to ensure that you can go to the next position for the first time
        while(flag==0 && count<7)//In the nextxy() function, when some positions have passed, it will return 0. At this time, let count + + try another available next position
        {
            count++;
            flag= nextxy(&x1,&y1,count);
        }
        while(flag)//Indicates that the next walkable position of the current position has been found
        {
            if(TravelChessBoard(x1,y1,tag+1))
            {
                return 1;
            }

            //If you follow the first x1 y1 step until there is repetition, then go back to the beginning and find the next step of the horse again
            //Find the next walking coordinate (x1,y1) of the horse. If flag=1 is found, otherwise it is 0
            x1=x;
            y1=y;
            count++;

            //This is the next step up and down
            flag= nextxy(&x1,&y1,count);
            while(flag==0 && count<7)
            {
                count++;
                flag= nextxy(&x1,&y1,count);
            }
        }

        if(0==flag)
        {
            chess[x][y]=0;//Look again
        }
        return 0;

}

void test_KinghtTraverse()
{
    int i,j;
    clock_t start, finish;
    start =clock();
    for(i=0;i<X;i++)
    {
        for(j=0;j<Y;j++)
        {
            chess[i][j]=0;
        }
    }

    if(!TravelChessBoard(2,0,1))//Starting position: second row, column 0
    {
        cout<<"Sorry, the horse failed to step on the chessboard!!!"<<endl;
    }

    finish=clock();
    cout<<"Total time for this calculation:"<<(double )(finish-start)/CLOCKS_PER_SEC<<"s"<<endl;//The number of CPU ticks divided by the number of CPU ticks per minute is seconds


}
int main() {

    test_KinghtTraverse();
    return 0;
}

The starting position of the horse is the second row and column 0

Operation results:

Breadth first traversal BFS

Explain from the figure on the right,

Let's start with A, take the right first principle, go to B first, and then f, because for A, B and F are the closest.

Therefore, the traversal order is ABF CIGE DH

fifo

Adjacency matrix breadth ergodic

//Breadth traversal of adjacency matrix
namespace LinJieMatrix
{
#include <iostream>

    using namespace std;
#define MAXVEX 100 			//  max vertex 
#define INFINITY 65535 		//  65535 is used to represent infinity

    typedef struct
    {
        char vexs[MAXVEX];				// Vertex table
        int arc[MAXVEX][MAXVEX];		// adjacency matrix 
        int numVertexes, numEdges;		// The current number of vertices and edges in the graph
    } MGraph;

// The adjacency matrix of undirected network graph is established
    void CreateMGraph(MGraph *G)
    {
        int i, j, k, w;
        int flag;
        printf("Please enter whether to generate undirected or directed, undirected input 0, directed input 1:\n");
        cin>>flag;
        printf("Please enter the number of vertices and edges:\n");
        scanf("%d %d", &G->numVertexes, &G->numEdges);

        for( i=0; i < G->numVertexes; i++ )
        {
            scanf("%c", &G->vexs[i]);
        }

        for( i=0; i < G->numVertexes; i++ )
        {
            for( j=0; j < G->numVertexes; j++ )
            {
                G->arc[i][j] = INFINITY;			// Adjacency matrix initialization
            }
        }

        if(flag==0)//Undirected
        {
            for( k=0; k < G->numEdges; k++ )
            {
                printf("Please enter an edge(Vi,Vj)Subscript on i,subscript j And corresponding rights w:\n");		// This is just an example. Improving the user experience needs to be improved
                scanf("%d %d %d", &i, &j, &w);
                G->arc[i][j] = w;
                G->arc[j][i] = G->arc[i][j];			// Is an undirected net graph, symmetric matrix
            }
        }
        else//Directed
        {
            for( k=0; k < G->numEdges; k++ )
            {
                printf("Please enter an edge(Vi,Vj)Subscript on i,subscript j And corresponding rights w:\n");		// This is just an example. Improving the user experience needs to be improved
                scanf("%d %d %d", &i, &j, &w);
                G->arc[i][j] = w;

            }
        }

    }
#define TRUE 1
#define FALSE 0
#define MAX 256
    typedef int Boolean;    // Here, we define Boolean as boolean type, and its value is TRUE or FALSE
    Boolean visited[MAX];    // Array of access flags

// Breadth traversal algorithm of adjacency matrix
    void BFSTraverse(MGraph G)
    {
        int i, j;
        Queue Q;

        for( i=0; i < G.numVertexes; i++ )
        {
            visited[i] = FALSE;
        }

        initQueue( &Q );//Initialize queue

        for( i=0; i < G.numVertexes; i++ )
        {
            if( !visited[i] )
            {
                printf("%c ", G.vexs[i]);
                visited[i] = TRUE;
                EnQueue(&Q, i);//Enter queue

                while( !QueueEmpty(Q) )
                {
                    DeQueue(&Q, &i);//Out of queue
                    //Traverse the vertices adjacent to vertex i
                    for( j=0; j < G.numVertexes; j++ )
                    {
                        if( G.arc[i][j]==1 && !visited[j] )//j is the adjacent vertex of i
                        {
                            printf("%c ", G.vexs[j]);
                            visited[j] = TRUE;
                            EnQueue(&Q, j);//Queue
                        }
                    }
                }
            }
        }
    }

}

Adjacency table - breadth traversal

//Adjacency table traversal
namespace LinJieTable_BFS {

#include <iostream>

    using namespace std;

#define MAXVEX 100

    typedef struct EdgeNode            // Edge table node
    {
        int adjvex;                    // The adjacent point field stores the subscript corresponding to the vertex
        int weight;                    // It is used to store weights. It is not required for non network graphs
        struct EdgeNode *next;        // Chain domain, pointing to the next adjacent node
    } EdgeNode;

    typedef struct VertexNode        // Vertex table node
    {
        char data;                    // Vertex domain, storing vertex information
        EdgeNode *firstEdge;        // Edge header pointer
    } VertexNode, AdjList[MAXVEX];

    typedef struct {
        AdjList adjList;
        int numVertexes, numEdges;    // The current number of vertices and edges in the graph
    } GraphAdjList;

// Establish the adjacency table structure of graph
    void CreateALGraph(GraphAdjList *G) {
        int i, j, k;
        EdgeNode *e;

        printf("Please enter the number of vertices and edges:\n");
        scanf("%d %d", &G->numVertexes, &G->numEdges);

        // Read vertex information and establish vertex table
        for (i = 0; i < G->numVertexes; i++) {
            scanf("%c", &G->adjList[i].data);
            G->adjList[i].firstEdge = NULL;        // Initialization set to empty table
        }

        //This is an undirected graph
        for (k = 0; k < G->numEdges; k++) {
            printf("Please enter an edge(Vi,Vj)Vertex sequence number on:\n");
            scanf("%d %d", &i, &j);

            //Head insertion
            e = (EdgeNode *) malloc(sizeof(EdgeNode));
            e->adjvex = j;                        // Adjacency serial number is j
            e->next = G->adjList[i].firstEdge;
            G->adjList[i].firstEdge = e;

            e = (EdgeNode *) malloc(sizeof(EdgeNode));
            e->adjvex = i;                        // Adjacency serial number is i
            e->next = G->adjList[j].firstEdge;
            G->adjList[j].firstEdge = e;
        }
    }


#define TRUE 1
#define FALSE 0
#define MAX 256
    typedef int Boolean;    // Here, we define Boolean as boolean type, and its value is TRUE or FALSE
    Boolean visited[MAX];    // Array of access flags




//Breadth traversal we traverse by the rules of adjacency table
    void BFS(GraphAdjList G) {
        int i, j;
        Queue Q;//queue


        for (i = 0; i < G.numVertexes; i++) {
            visited[i] = FALSE;
        }
        initQueue(&Q);//Initialize queue


        for (i = 0; i < G.numVertexes; i++) {
            if (!visited[i]) {
                printf("%c ", G.adjList[i].data);
                visited[i] = TRUE;
                EnQueue(&Q, i);//Enter queue

                while (!QueueEmpty(Q)) {
                    DeQueue(&Q, &i);//Out of queue
                    //Traverse the vertices adjacent to vertex i
                    for (j = 0; j < G.numVertexes; j++) {
                        EdgeNode *e;//Adjacent edge node
                        e = G.adjList[i].firstEdge;//e points to the adjacent edge node of i
                        if (e && !visited[e->adjvex])//E - > adjvex is the vertex j
                        {
                            printf("%c ", e->adjvex);
                            visited[e->adjvex] = TRUE;
                            EnQueue(&Q, e->adjvex);//Queue
                        }
                        e = e->next;//Point to the next edge node adjacent to i
                    }
                }
            }
        }


    }
}

Weighted minimum spanning tree

Prim algorithm

with PPT take as an example
                   subscript:    0 	1  	2   	3  	4   	5   	6  	7  	8  
initialization: lowcost[]:   0 	10 	∞  	∞ 	∞ 	11	∞ 	∞ 	∞ -----weight
               adjvex[]:   0 	0   	0   	0  	0  	0   	0  	0  	0 ------The relationship between vertices, such as: [0 0 0 1 0 0 0 1 2]Indicates that the third vertex, the seventh vertex is associated with the first vertex, and the eighth vertex is associated with the second vertex
 Each cycle starts with subscript 1
--------------
First cycle:

min=10
k=1
 Output:(0,1) That is( A,B)
lowcost[1]=0 express B This point has been visited.
                   subscript:    0 	1  	2   	3  	4   	5   	6  	7  	8  
             lowcost[]:   0 	0 	∞  	∞ 	∞ 	11	∞ 	∞ 	∞ -----weight
               adjvex[]:   0 	0   	0   	0  	0  	0   	0  	0  	0 ------The relationship between vertices, such as: [0 0 0 1 0 0 0 1 2]Indicates that the third vertex, the seventh vertex is associated with the first vertex, and the eighth vertex is associated with the second vertex

adjacency matrix  k Traverse all vertices one by one
	lowcost[]:   0 	0 	∞  	∞ 	∞ 	11	∞ 	∞ 	∞ -----weight
		 10 	0	18	∞	∞	∞	16	∞	12
 The two compare starting with subscript 1 and assign a small value to lowcost[],meanwhile adjvex[j] = k     j Representative column represents row
adjvex[]:   0 	0   	0   	0  	0  	0   	0  	0  	0 ------The relationship between vertices, such as: [0 0 0 1 0 0 0 1 2]Indicates that the third vertex, the seventh vertex is associated with the first vertex, and the eighth vertex is associated with the second vertex


to update lowcost[] adjvex[]
lowcost[]:   0 	0 	18  	∞ 	∞ 	11	16 	∞ 	12 -----weight
adjvex[]:     0 	0   	1   	0  	0  	0   	1  	0  	1
--------------

--------------
Second cycle

min=11
k=5
 Output: (0, 5) that is( A,F)
lowcost[5]=0 express F This point has been visited.
lowcost[]:   0 	0 	18  	∞ 	∞ 	0	16 	∞ 	12 -----weight
adjvex[]:     0 	0   	1   	0  	0  	0   	1  	0  	1

adjacency matrix  k Traverse all vertices one by one
lowcost[]:   0 	0 	18  	∞ 	∞ 	0	16 	∞ 	12 -----weight
	  11	∞	∞	∞	26	0	17	∞	∞

The two compare starting with subscript 1 and assign a small value to lowcost[],meanwhile adjvex[j] = k     j Representative column represents row
adjvex[]:     0 	0   	1   	0  	0  	0   	1  	0  	1

to update lowcost[] adjvex[]
lowcost[]:   0 	0 	18  	∞ 	26 	0	16 	∞ 	12 -----weight
adjvex[]:     0 	0   	1   	0  	5  	0   	1  	0  	1	
--------------

--------------
Third cycle
min=12
k=8
 Output: (1, 8) that is( B,I)

lowcost[8]=0 express I This point has been visited.

lowcost[]:   0 	0 	18  	∞ 	26 	0	16 	∞ 	12 -----weight
adjvex[]:     0 	0   	1   	0  	5  	0   	1  	0  	1	

adjacency matrix  k Traverse all vertices one by one

lowcost[]:   0 	0 	18  	∞ 	26 	0	16 	∞ 	12 -----weight
	 ∞	12	8	21	∞	∞	∞	∞	0
 The two compare starting with subscript 1 and assign a small value to lowcost[],meanwhile adjvex[j] = k     j Representative column represents row
adjvex[]:     0 	0   	1   	0  	5  	0   	1  	0  	1	

to update lowcost[] adjvex[]
lowcost[]:   0 	0 	8  	21 	26 	0	16 	∞ 	0 -----weight
adjvex[]:     0 	0   	8   	8  	5  	0   	1  	0  	8

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

--------------
Fourth cycle
min=8
k=2
 Output: (8, 2) that is( I,C)
lowcost[2]=0 express C This point has been visited.
lowcost[]:   0 	0 	8  	21 	26 	0	16 	∞ 	0 -----weight
adjvex[]:     0 	0   	8   	8  	5  	0   	1  	0  	8
 adjacency matrix  k Traverse all vertices one by one
lowcost[]:   0 	0 	8  	21 	26 	0	16 	∞ 	0 -----weight
	 ∞	18	0	22	∞	∞	∞	∞	8
 The two compare starting with subscript 1 and assign a small value to lowcost[],meanwhile adjvex[j] = k     j Representative column represents row
adjvex[]:     0 	0   	8   	8  	5  	0   	1  	0  	8
 to update lowcost[] adjvex[]
lowcost[]:   0 	0 	0  	21 	26 	0	16 	∞ 	0 -----weight
adjvex[]:     0 	0   	2   	8  	5  	0   	1  	0  	8
--------------

--------------
Fifth cycle
min=16
k=6
 Output: (1, 6) that is( B,G)
and so on

The source code is as follows:

// Prim algorithm generates minimum spanning tree based on adjacency matrix
void MiniSpanTree_Prim(MGraph G)
{
	int min, i, j, k;
	int adjvex[MAXVEX];		// Save the relevant vertex subscripts. For example, [0 0 1 0 0 1 2] indicates that the third vertex, the seventh vertex is associated with the first vertex, and the eighth vertex is associated with the second vertex
	int lowcost[MAXVEX];	// Save the weights of edges between related vertices
	
	lowcost[0] = 0;			// V0 starts to traverse as the root of the minimum spanning tree, and the weight is 0
	adjvex[0] = 0;			// V0 is the first to join
	
	// Initialization operation
	for( i=1; i < G.numVertexes; i++ )
	{
		lowcost[i] = G.arc[0][i];	// Add the ownership value of row 0 of adjacency matrix to the array first
		adjvex[i] = 0;				// Initialize all subscripts to V0 first
	}
	//Take PPT as an example
	//So far, the value in lowcast [] is 0 10 INFINITY INFINITY INFINITY 11 INFINITY INFINITY INFINITY infinity
	
	// The process of constructing the minimum spanning tree
	for( i=1; i < G.numVertexes; i++ )
	{
		min = INFINITY;		// The initialization minimum weight is 65535 and other impossible values
		j = 1;
		k = 0;
		
		// Traverse all vertices
		while( j < G.numVertexes )
		{
			// Find the minimum weight stored in the lowcast array
			if( lowcost[j]!=0 && lowcost[j] < min )// Lowcast [J]! = 0 means you don't point to yourself
			{
				min = lowcost[j];//Find the smallest weight
				k = j;		// Store the subscript of the found minimum weight in k for use. k = 1 and k = 5
			}
			j++;
		}
		
		// Prints the edge with the lowest weight among the current vertex edges
		printf("(%d,%d)", adjvex[k], k);//
		lowcost[k] = 0;		// Setting the weight of the current vertex to 0 indicates that this vertex has completed the task and traverses the next vertex
		//For vertex A, the edge with the smallest weight is vertex B, so k=1
		// k rows of adjacency matrix traverse all vertices one by one
		//For the edges between vertices that have passed, set it to 0 to update the relationship between vertices
		for( j=1; j < G.numVertexes; j++ )
		{
		    //Compare the weight of the vertex connected with k with the weight of the vertex associated with the previous vertex
			if( lowcost[j]!=0 && G.arc[k][j] < lowcost[j] )
			{

				lowcost[j] = G.arc[k][j];//Update the weight. Select the smallest weight. The subscript of the weight represents the label of the vertex  
				                         // This step is the most critical. Here is the principle of updating the weight. We take out the weight of the k-th vertex and other vertex edges, compare it with the original weight array, and select the smaller one to update the weight array. In order to reach the j-th vertex, it is the smallest weight
				                         
				adjvex[j] = k;	         //Updates the connection between vertices
                                          //Then, the updated weight array will be used in the next big cycle, and the smallest vertex will be selected. At this time, adjvex is also updated, so the k-th vertex to adjvex[k] th vertex is the minimum weight
			}
		}
	}
}

Kruskal algorithm

Graph structure based on edge set array

If the edge (0,3) is added, then 0,2,3,5 will form a loop, not a tree.

Similarly, just choose one of (1, 2) and (4, 2)

At this point, it is determined that the loop (5, 6) cannot be added

And the next (1, 2) is also determined to form a loop and cannot be added

Here we can see the function of the parent array, which actually associates the vertices of the tree.

For example (5, 6):

For 5, parent [5] = 8, parent [8] = 6, parent [6] = 0 returns 6

For 6, parent[6]=0, return 6, n==m, then form a loop, not a tree, and do not join this edge

The back (3, 4) also forms a loop and does not join this side

Then the back will form a loop!

This algorithm is better understood!!! Because the edge set structure used is better understood.

For sparse graphs (that is, there are not so many edges), krukars algorithm has advantages.

For dense graphs (with fewer vertices and more edges), PRIM algorithm has advantages.

The code is as follows:

int Find(int *parent, int f)
{
	while( parent[f] > 0 )
	{
		f = parent[f];
	}
	
	return f;
}

// Generating minimum spanning tree by Kruskal algorithm
void MiniSpanTree_Kruskal(MGraph G)
{
	int i, n, m;
	Edge edges[MAGEDGE];	// Define edge set array
	int parent[MAXVEX];		 definition parent Array is used to determine whether edges form a loop with each other
	
	for( i=0; i < G.numVertexes; i++ )//Initialize parent
	{
		parent[i] = 0;
	}
	
	for( i=0; i < G.numEdges; i++ )
	{
		n = Find(parent, edges[i].begin);	// 4 2 0 1 5 3 8 6 6 6 7
		m = Find(parent, edges[i].end);		// 7 8 1 5 8 7 6 6 6 7 7
		
		if( n != m )		// If n==m, a loop is formed, which is not satisfied!
		{
			parent[n] = m;	// Put the end vertex of this edge into the parent array with subscript as the starting point, indicating that this vertex is already in the spanning tree collection
			printf("(%d, %d) %d ", edges[i].begin, edges[i].end, edges[i].weight);
		}
	}
}

Shortest path

Dijestra

final[MAXVEX];     // final[w] = 1 indicates that the shortest path from vertex V0 to Vw has been obtained
(*D)[w] = min + G.arc[k][w];	// Modify the current path length to store the weight and of the shortest path to each point
(*p)[w] = k;					// Store the precursor vertex. For example, p[2]=1 means that the precursor vertex of 2 is 1, that is, the array used to store the shortest path subscript from vertex 1 to vertex 2

#define MAXVEX	9
#define	INFINITY	65535

typedef	int	Patharc[MAXVEX];			// An array used to store the shortest path subscripts
typedef int	ShortPathTable[MAXVEX];		// Used to store the weight sum of the shortest path to each point

void ShortestPath_Dijkstar(MGraph G, int V0, Patharc *P, ShortPathTable *D)
{
	int v, w, k, min;
	int final[MAXVEX];		// final[w] = 1 indicates that the shortest path from vertex V0 to Vw has been obtained
	
	// Initialization data
	for( v=0; v < G.numVertexes; v++ )
	{
		final[v] = 0;				// All vertices initialized to the shortest path not found
		(*D)[V] = G.arc[V0][v];		// Add weight to the vertex connected with V0 point
		(*P)[V] = 0;				// Initialize path array P to 0
	}
	(*D)[V0] = 0;		// The path from v0 to V0 is 0
	final[V0] = 1;		// No path is required from V0 to V0
	
	// Start the main loop and find the shortest path from V0 to a V vertex each time
	for( v=1; v < G.numVertexes; v++ )
	{
		min = INFINITY;
		for( w=0; w < G.numVertexes; w++ )
		{
			if( !final[w] && (*D)[w]<min )
			{
				k = w;
				min = (*D)[w];
			}
		}
		final[k] = 1;	// Set the nearest vertex currently found to 1
		
		// Correct the current shortest path and distance
		for( w=0; w < G.numVextexes; w++ )
		{
			// If the path through v vertex is shorter than the current path, update!
			if( !final[w] && (min+G.arc[k][w] < (*D)[w]) )//It's very important here. For example, when 0 goes to 1, it takes min + g.arc [k] [w] < (* d) [w]) to choose whether to go from 1 to 2 or from 0 to 2
			{
				(*D)[w] = min + G.arc[k][w];	// Modify the current path length
				(*p)[w] = k;					// Store precursor vertex
			}
		}
	}
}

Final result

final[MAXVEX];     // final[w] = 1 indicates that the shortest path from vertex V0 to Vw has been obtained
(*D)[w] = min + G.arc[k][w];	// Modify the current path length to store the weight and of the shortest path to each point
(*p)[w] = k;					// Store the precursor vertex. For example, p[2]=1 means that the precursor vertex of 2 is 1, that is, the array used to store the shortest path subscript from vertex 1 to vertex 2

N Represents infinity, which is 65535 in the code
 initialization:
final: 	1	0	0	0	0	0	0	0	0
D:            0	1	5	N	N	N	N	N	N           
P: 	0	0	0	0	0	0	0	0	0	

from v=1 start v Represents vertex 1
**********First main cycle
k=1;
min=1;

to update final express V0 reach Vk Shortest path found
final: 	1	1	0	0	0	0	0	0	0

to update D ,P
D:            0	1	4	N	N	N	N	N	N           
P: 	0	0	1	0	0	0	0	0	0
**********First main cycle




**********Second main cycle

final: 	1	1	0	0	0	0	0	0	0
D:            0	1	4	N	N	N	N	N	N           
P: 	0	0	1	0	0	0	0	0	0

k=2;
min=4;

to update final express V0 reach Vk Shortest path found
final: 	1	1	1	0	0	0	0	0	0
 to update D ,P
D:            0	1	4	N	5	N	N	N	N           
P: 	0	0	1	0	2	0	0	0	0
**********Second main cycle





**********Third main cycle
final: 	1	1	1	0	0	0	0	0	0
D:            0	1	4	N	5	N	N	N	N           
P: 	0	0	1	0	2	0	0	0	0

k=4;
min=5;
to update final express V0 reach Vk Shortest path found
final: 	1	1	1	0	1	0	0	0	0
 to update D ,P
D:            0	1	4	7	5	N	N	N	N           
P: 	0	0	1	4	2	0	0	0	0

**********Third main cycle

**********Fourth main cycle
final: 	1	1	1	0	1	0	0	0	0
D:            0	1	4	7	5	N	N	N	N           
P: 	0	0	1	4	2	0	0	0	0

k=3;
min=7;
to update final express V0 reach Vk Shortest path found
final: 	1	1	1	1	1	0	0	0	0
 to update D ,P
D:            0	1	4	7	5	N	10	N	N           
P: 	0	0	1	4	2	0	3	0	0
**********Fourth main cycle

**********Fifth main cycle
final: 	1	1	1	1	1	0	0	0	0
D:            0	1	4	7	5	N	10	N	N           
P: 	0	0	1	4	2	0	3	0	0

k=6;
min=10
 to update final express V0 reach Vk Shortest path found
final: 	1	1	1	1	1	0	1	0	0
 to update D ,P
D:            0	1	4	7	5	N	10	12	N           
P: 	0	0	1	4	2	0	3	6	0
**********Fifth main cycle


**********Sixth main cycle
final: 	1	1	1	1	1	0	1	0	0
D:            0	1	4	7	5	N	10	12	N           
P: 	0	0	1	4	2	0	3	6	0

k=7;
min=12;
to update final express V0 reach Vk Shortest path found
final: 	1	1	1	1	1	0	1	1	0
 to update D ,P
D:            0	1	4	7	5	N	10	12	16           
P: 	0	0	1	4	2	0	3	6	7
**********Sixth main cycle


**********Seventh main cycle
final: 	1	1	1	1	1	0	1	1	0
D:            0	1	4	7	5	N	10	12	16          
P: 	0	0	1	4	2	0	3	6	7
k=8;
min=14;
to update final express V0 reach Vk Shortest path found
final: 	1	1	1	1	1	0	1	1	1
 to update D ,P
D:            0	1	4	7	5	N	10	12	16          
P: 	0	0	1	4	2	0	3	6	7
**********Seventh main cycle

**********Eighth main cycle
final: 	1	1	1	1	1	0	1	1	1
D:            0	1	4	7	5	N	10	12	16          
P: 	0	0	1	4	2	0	3	6	7
**********Eighth main cycle

End cycle
final: 	1	1	1	1	1	0	1	1	1
D:       0	1	4	7	5	N	10	12	16          
P: 		0	0	1	4	2	0	3	6	7
 The route is 0->1->2->4->3->6->7->8

Freud

#define MAXVEX	9
#define INFINITY	65535

typedef int Pathmatirx[MAXVEX][MAXVEX];
typedef int ShortPathTable[MAXVEX][MAXVEX];

void ShortestPath_Floyd(MGraph G, Pathmatirx *P, ShortPathTable *D)
{
	int v, w, k;
	
	// Initialize D and P
	for( v=0; v < G.numVertexes; v++ )
	{
		for( w=0; w < G.numVertexes; w++ )
		{
			(*D)[v][w] = G.matirx[v][w]; //Get adjacency matrix
			(*P)[v][w] = w;//Initializes the precursor node between the edges
		}
	}
	
	// Beautiful Freudian algorithm
	//This three-layer loop takes into account all the edges and between the two
	//For D arrays
	//The element of D to be changed is internally controlled by two variables v,w, that is, the edge (v,w)
	//For example, (0,2), that is, the route 0 - > 2, will correspond to the following situations (0,2) > (0,0) + (0,2) (0,2) > (0,1) + (1,2)
	//                                                 That is, from 0 to 2, we can go like this: from 0 to 1, and then from 1 to 2
	//                                                 (V, w) > (V, K) + (k, w), K plays the role of changing the route, while V, W is the vertex responsible for both ends of the edge
	//For P array (* P)[v][w] = (*P)[v][k]; In other words, for the (v,w) direction, the route of (v,k) - > (k, w) can be used, so for the (v,w) W, its precursor node is k!!!
	//After a three-tier cycle, all situations can be taken into account
	//For example, there are several ways for 0 - > 3, 0 - > 1 + 1 - > 3 
	//                       0->2 + 2->3 =0->1 + 1->2 + 2->4 + 4->3
    //                      The above two cases will be taken into account, so Freud's algorithm is very simple, but the event complexity is high O (n^3)
	for( k=0; k < G.numVertexes; k++ )
	{
		for( v=0; v < G.numVertexes; v++ )
		{
			for( w=0; w < G.numVertexes; w++ )
			{
				if( (*D)[v][w] > (*D)[v][k] + (*D)[k][w] )//Here v stands for column k
				{
					(*D)[v][w] = (*D)[v][k] + (*D)[k][w];
					(*P)[v][w] = (*P)[v][k];		// Please think: can I change it here to (* P)[k][w]? Why?
				}
			}
		}
	}
}

Topological sorting

The topology must point from the front to the back

Use adjacency table

// Edge table node declaration
typedef struct EdgeNode
{
	int adjvex;
	struct EdgeNode *next;
}EdgeNode;

// Vertex table node declaration
//Adjacency table
typedef struct VertexNode
{
	int in;			// Vertex penetration
	int data;
	EdgeNode *firstedge;
}VertexNode, AdjList[MAXVEX];

//Directed graph structure
typedef struct
{
	AdjList adjList;
	int numVertexes, numEdges;
}graphAdjList, *GraphAdjList;

// Topological sorting algorithm
// If GL has no loop, output the topology sorting sequence and return OK, otherwise return ERROR
Status TopologicalSort(GraphAdjList GL)
{
	EdgeNode *e;
	int i, k, gettop;
	int top = 0;		// Index used for stack pointer subscript
	int count = 0;		// Used to count the number of output vertices
	int *stack;			// Used to store vertices with a penetration of 0
	
	stack = (int *)malloc(GL->numVertexes * sizeof(int));

	//Stack subscripts of vertices read as 0
	for( i=0; i < GL->numVertexes; i++ )
	{
		if( 0 == GL->adjList[i].in )
		{
			stack[++top] = i;	// Subscript vertices with a degree of 0 onto the stack
		}
	}
	//Here top is 12

	while( 0 != top )
	{
		gettop = stack[top--];	// Out of stack
		printf("%d -> ", GL->adjList[gettop].data);
		count++;				

		//Here is the vertex adjacent to the vertex in the traversal stack
		for( e=GL->adjList[gettop].firstedge; e; e=e->next )
		{
			k = e->adjvex;
			// Note: the following if condition is the key point of analyzing the whole program!
			// Set the penetration of the adjacent contact of vertex k to - 1, because its precursor has been eliminated
			// Then, judge whether the input degree after - 1 is 0. If it is 0, it will also be put on the stack
			if( !(--GL->adjList[k].in) )	//Because according to the principle of the algorithm, every vertex read as zero is taken out. After it is used up, it is deleted from the graph. Therefore, its adjacent vertex penetration will be - 1 accordingly
			                                //If the degree of GL - > adjlist [k] is 0, it will also be stacked
			{
				stack[++top] = k;
			}
		}
	}
	
	if( count < GL->numVertexes )	// If count is less than the number of vertices, there is a ring
	{
		return ERROR;
	}
	else
	{
		return OK;
	}
}

critical path

etv is pushed from left to right

ltv is pushed from right to left

For vertices

Vertex j follows vertex i and is adjacent

Earliest occurrence time of vertex Vi + (vi,vj) weight = earliest occurrence time of vertex j

Latest occurrence time of vertex Vj - (vi,vj) weight = latest occurrence time of vertex i

For example:

For the ltv of C8, this can be understood

The latest occurrence time of C8 is 8 and the earliest occurrence time is 7, indicating that C8 can be lazy for an hour. Why? Because it takes 5 hours from vertex 5 to vertex 8, and only 4 hours from vertex 6 to vertex 8

If vertex 8 wants to start working, it must take both routes. If 5 - > 8 takes a long time, then 6 - > 8 can certainly be lazy

For arcs. They are the duration of time

Vertex k follows vertex j and is adjacent

Earliest occurrence time of arc between vertex k and vertex j = earliest occurrence time of vertex j

The latest occurrence time of the arc between vertex k and vertex j = the latest occurrence time of vertex k - the weight between vertex k and vertex j

For example:

For arc a4, the earliest occurrence time of ete is the earliest occurrence time etv of vertex C2.

lte is also pushed from right to left. For example, the latest occurrence time of a11 and a11 lte = the latest occurrence time of vertex C9 – 4 = 16-4 = 12, and so on.

Summary:

For vertices:
    
vertex j At vertex i Behind and adjacent
 vertex Vi Earliest occurrence time of +(vi,vj)Right of = vertex j Earliest occurrence time of
 vertex Vj Latest occurrence time of -(vi,vj)Right of = vertex i Latest occurrence time of

For arcs. They are the duration of time:

vertex k At vertex j Behind and adjacent
 vertex k And vertex j Earliest occurrence time of arc between=vertex j Earliest occurrence time of
 vertex k And vertex j Latest occurrence time of arc between= vertex k Latest occurrence time of- vertex k And vertex j Right between

// Edge table node declaration
typedef struct EdgeNode
{
	int adjvex;
	struct EdgeNode *next;
}EdgeNode;

// Vertex table node declaration
typedef struct VertexNode
{
	int in;			// Vertex penetration
	int data;
	EdgeNode *firstedge;
}VertexNode, AdjList[MAXVEX];

typedef struct
{
	AdjList adjList;
	int numVertexes, numEdges;
}graphAdjList, *GraphAdjList;

int *etv, *ltv;
int *stack2;			// Stack for storing topological sequences
int top2;				// Stack top pointer for stack2

// Topological sorting algorithm
// If GL has no loop, output the topology sorting sequence and return OK, otherwise return ERROR
/**
 * The topological order is obtained, and the etv is obtained
 * @param GL
 * @return
 */
Status TopologicalSort(GraphAdjList GL)
{
	EdgeNode *e;
	int i, k, gettop;
	int top = 0;		// Index used for stack pointer subscript
	int count = 0;		// Used to count the number of output vertices
	int *stack;			// Used to store vertices with a penetration of 0
	
	stack = (int *)malloc(GL->numVertexes * sizeof(int));
	
	for( i=0; i < GL->numVertexes; i++ )
	{
		if( 0 == GL->adjList[i].in )
		{
			stack[++top] = i;	// Subscript vertices with a degree of 0 onto the stack
		}
	}
	
	// Initialization etv is 0
	top2 = 0;
	etv = (int *)malloc(GL->numVertexes*sizeof(int));
	for( i=0; i < GL->numVertexes; i++ )
	{
		etv[i] = 0;
	}
	stack2 = (int *)malloc(GL->numVertexes*sizeof(int));
	
	while( 0 != top )
	{
		gettop = stack[top--];		// Out of stack
		// printf("%d -> ", GL->adjList[gettop].data); 
		stack2[++top2] = gettop;	// Save topology sequence order C1 C2 C3 C4.... C9
		count++;				
		
		for( e=GL->adjList[gettop].firstedge; e; e=e->next )
		{
			k = e->adjvex;//k is the adjacent vertex
			// Note: the following if condition is the key point of analyzing the whole program!
			// Set the penetration of the adjacent contact of vertex k to - 1, because its precursor has been eliminated
			// Then, judge whether the input degree after - 1 is 0. If it is 0, it will also be put on the stack
			//Here is topological sorting
			if( !(--GL->adjList[k].in) )
			{
				stack[++top] = k;
			}

            //
			if( (etv[gettop]+e->weight) > etv[k] )//This step is very important. It is used to calculate the earliest occurrence time of vertices. It is better to understand it according to the picture of PPT
			                                      //A large value is the earliest occurrence time of vertex k, which is equivalent to the earliest occurrence time of vertex Vi + (vi,vj) weight = the earliest occurrence time of vertex j
			{
				etv[k] = etv[gettop] + e->weight;
			}
		}
	}
	
	if( count < GL->numVertexes )	// If count is less than the number of vertices, there is a ring
	{
		return ERROR;
	}
	else
	{
		return OK;
	}
}

// Find the critical path, GL is a directed graph, and output the key activities of GL
void CriticalPath(GraphAdjList GL)
{
	EdgeNode *e;
	int i, gettop, k, j;
	int ete, lte;
	
	// Call the improved topology sorting to find the values of etv and stack2
	TopologicalSort(GL);
	
	// Time to initialize ltv to sink
	ltv = (int *)malloc(GL->numVertexes*sizeof(int));
	for( i=0; i < GL->numVertexes; i++ )
	{
		ltv[i] = etv[GL->numVertexes-1];
	}
	
	// Calculate ltv one by one from the sink
	while( 0 != top2 )
	{
		gettop = stack2[top2--];	// Note that the first out of the stack is the sink. The first out of the stack sink is actually useless because its first edge points to null
		                            //When it comes to C8, the real calculation begins
		for( e=GL->adjList[gettop].firstedge; e; e=e->next )
		{
			k = e->adjvex;
			if( (ltv[k] - e->weight) < ltv[gettop] )//Here you need to fill in a small one. In order not to delay the construction period, you can understand the code from the ltv of the source point
			{
				ltv[gettop] = ltv[k] - e->weight;//The latest occurrence time of vertex gettop = the latest occurrence time of vertex k - the weight between vertex gettop and vertex k
			}
		}
	}
	
	// Find ete and lte through etv and ltv
	for( j=0; j < GL->numVertexes; j++ )
	{
	    //Traverse the left and right adjacent vertices of vertices
		for( e=GL->adjList[j].firstedge; e; e=e->next )
		{
			k = e->adjvex;//Get adjacent vertices
			ete = etv[j];//The earliest occurrence time of the arc between ete vertex k and vertex j = the earliest occurrence time of vertex j
			lte = ltv[k] - e->weight;//The latest occurrence time of the arc between lte vertex k and vertex j = the latest occurrence time of vertex k - the weight between vertex k and vertex j
			
			if( ete == lte )//Print if ete equals lte
			{
				printf("<v%d,v%d> length: %d , ", GL->adjList[j].data, GL->adjList[k].data, e->weight );
			}
		}
	}
}

Final result

Search algorithm

Sequential search

Half search

Interpolation lookup (find by scale)

Interpolation is to use the scale to get the closest position.

The time complexity of interpolation method and half method is O(log2n).

On average, the performance of interpolation method is higher than that of half method

However, if the data growth is extremely uneven, such as from 1 to 1000 to 10000 to 100000000, the efficiency of the interpolation method will not work at this time, because its proportion is meaningless

Fibonacci search (golden ratio search)

//We can see from the code
//In fact, it uses the golden ratio to locate mid
//Conditions: (1) data must adopt sequential storage structure; (2) The data must be in order.
//Principle: (1) the Fibonacci value closest to the search length is used to determine the split point; (2) Golden section.
int Fibonacci_Search(int *a,int n,int key)
{
    int low,high,mid,i,k;
    low=1;
    high=n;//Maximum subscript of a array
    k=0;
    while(n>F[k]-1)//Calculate the weizhi of n in Fibonacci sequence
    {
        k++;
    }
    
    for(i=n;i<F[k]-1;i++)//Complete the dissatisfied value
    {
        a[i]=a[n];
    }
    
    while(low<=high)
    {
        mid=low+F[k-1]-1;//Calculates the subscript of the current separator
        if(key<a[mid])//
        {
            high=mid-1;//Adjust highest subscript
            k=k-1;//Fibonacci sequence subscript-1
        }
        else if(key>a[mid])
        {
            low=mid+1;//Adjust lowest subscript
            k=k-2;//Fibonacci sequence subscript-2
        }
        else//equal
        {
            if(mid<=n)
                return mid;
            else//If mid > n indicates an incomplete value, n is returned
                return n;
        }   
    }
    return 0; 
}

Reference blog

Linear index lookup

Dense index

Dense index is used when the amount of data is not particularly large.

Block index

Inverted index

Binary sort tree

Binary sort tree is generated according to size

The general principle is that the big one is on the right and the small one is on the left

Binary sort tree lookup

Binary sort tree insert

Binary sort tree delete

#include <iostream>
typedef struct BiTNode
{
    int data;
    struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;

typedef int Status;
#define TRUE 1
#define FALSE 0

//Binary tree sort lookup
Status SearchBST()
{

}

/**
 * Specific deletion operation
 * @param p
 * @return
 */
Status Delete(BiTree *p)
{
    BiTree  q, s;
    if((*p)->rchild==NULL)//The right subtree is empty
    {
        q=*p;
        *p=(*p)->lchild;//Pick up the left sub tree
        free(q);
    }
    else if((*p)->lchild==NULL)//Left subtree is empty
    {
        q=*p;
        *p=(*p)->rchild;//Connect the right subtree
        free(q);
    }
    //If the left and right subtrees are empty, just use the method that the top right subtree is empty
    else//The left and right subtrees are not empty
    {
        //Replace with direct precursor
        //How to find a direct precursor? Let s point directly to the left subtree of * p
        //Then find the right subtree at the bottom of s, which is the precursor node
        q=*p;
        s=(*p)->lchild;
        while(s->rchild)
        {
            q=s;
            s=s->rchild;
        }
        (*p)->data=s->data;
        if(q!=*p)//q here should be the precursor node of s
        {
            q->rchild=s->lchild;//Right subtree of reconnected q
        }
        else//That is, the left subtree of * p has no right subtree
        {
            q->lchild=s->lchild;//Reconnect the left subtree of Q, where q is actually (* p)
        }
        free(s);
    }
    return TRUE;

}

/**
 * Binary tree sort delete operation
 * @param T
 * @param key
 * @return
 */
Status DeleteBST(BiTree *T,int key)
{
    if(!*T)
    {
        return FALSE;
    }
    else
    {
        if(key==(*T)->data)//Find the node to delete
        {
            return Delete(T);
        }
        else if(key<(*T)->data)//If the target value is less than the value of the current node, it is called recursively into the left subtree of the current node
        {
            return DeleteBST(&(*T)->lchild,key);
        }
        else                    //If the target value is greater than the value of the current node, it will be called recursively to enter the right subtree of the current node
        {
            return DeleteBST(&(*T)->rchild,key);
        }
    }
}

balanced binary tree

The figure above is a balanced binary sort tree

The above figure is not a balanced binary sort tree. It is not even a binary sort tree

The above figure is not a balanced binary sort tree either, because for 9 node, the left subtree depth is 2, the right subtree depth is 0, and 2-0 = 2 does not meet the condition of balanced binary tree

The above figure is a balanced binary sort tree

How to convert Figure 3 into the balanced binary sort tree in Figure 4.

Whenever this node is inserted, check whether this node will cause imbalance, that is, whether the balance factor is greater than 1.

For example, when node 6 is inserted, the balance factor of node 9 is > 1.

9, 7 and 6 constitute the smallest tree.

Let's ignore 8 this node first

[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-lxgduas7-1632886438959) (C: \ users \ Dell \ appdata \ roaming \ typora \ user images \ image-20210923150821420. PNG)]

principle

The figure above is an ordinary binary sort tree

How to turn the ordinary binary sort tree in the figure above into a balanced binary sort tree? Let's do it step by step!!!

BF > 1 right rotation

BF < - 1 left rotation

When node 9 comes in, it leads to node 4 BF=-2, node 6 BF=-2, node 7 BF=-2 and node 10 BF=1. It is strange that only the BF of node 10 is positive

This is obviously not in line with the rules of binary tree sorting.

So we should deal with 9 and 10 first

Let the BF of nodes 4, 6, 7, 9 and 10 be negative

Join node 8

The BF of node 4 and node 6 is - 2, and the BF of node 9 is 1, which is a positive number

So we should first deal with node 7 8 9 10 so that the BF of node 7 9 10 is also negative

realization

#include <iostream>
typedef struct BiTNode
{
    int data;
    int bf;//Equilibrium factor
    struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;

typedef int Status;
#define TRUE 1
#define FALSE 0
#define LH 1 / / the left subtree is too high
#define EH 0 / / left and right subtrees are equal in height
#define RH -1 / / the right subtree is too high


/**
 * Right rotation
 * @param p
 */
void R_Rotate(BiTree *p)
{
    BiTree L;
    L=(*p)->lchild;
    (*p)->lchild=L->rchild;
    L->rchild=(*p);
    *p=L;//Point to the new root node
}

/**
 * Left rotation
 * @param p
 */
void L_Rotate(BiTree *p)
{
    BiTree R;
    R=(*p)->rchild;
    (*p)->rchild=R->lchild;
    R->lchild=(*p);
    *p=R;//Point to the new root node
}


/**
 * Left balance
 * @param T
 */
void LeftBalance(BiTree *T)
{
    BiTree L,Lr;
    L=(*T)->lchild;
    switch (L->bf)//T's left child's bf
    {
        case LH://This indicates that L is the same sign as BF of the root node, and the root node can be rotated right, and the balance is restored after rotation, so the value of BF should also be modified
            (*T)->bf=L->bf=EH;
            R_Rotate(T);
            break;
        case RH://This indicates that L is opposite to the BF symbol of the root node. Rotate L left and then rotate the root node right
            Lr=L->rchild;
            //It's the switch below. I can't figure it out!!!!
            switch (Lr->bf)
            {
                case LH://
                    (*T)->bf=RH;
                    L->bf=EH;
                    break;
                case EH://
                    (*T)->bf=L->bf=EH;
                    break;
                case RH://
                    (*T)->bf=EH;
                    L->bf=LH;
                    break;
            }
            Lr->bf=EH;
            L_Rotate(&(*T)->lchild);//Make symbols the same
            R_Rotate(T);
            break;
    }
}

/**
 * Right balance
 * @param T
 */
void RightBalance(BiTree *T)
{
    BiTree R,Rl;
    R=(*T)->rchild;
    switch (R->bf)//T's left child's bf
    {
        case RH://This indicates that R is the same sign as BF of the root node, and the root node can be rotated to the left, and the balance is restored after rotation, so the value of BF should also be modified
            (*T)->bf=R->bf=EH;
            L_Rotate(T);
            break;
        case LH://This indicates that R is opposite to the BF symbol of the root node. Rotate r right and then rotate the root node left
            Rl=R->lchild;
            //It's the switch below. I can't figure it out!!!!
            switch (Rl->bf)
            {
                case RH://You can also draw a picture and assume
                    (*T)->bf=LH;
                    R->bf=EH;
                    break;
                case EH://
                    (*T)->bf=R->bf=EH;
                    break;
                case LH:// Here you can draw your own picture and suppose 
                    (*T)->bf=EH;
                    R->bf=RH;
                    break;
            }
            Rl->bf=EH;
            R_Rotate(&(*T)->rchild);//Make symbols the same
            L_Rotate(T);
            break;
    }
}



/**
 *
 * @param T
 * @param e Inserted data
 * @param taller If the tree grows tall, it will be unbalanced
 * @return
 */
int InsertAVL(BiTree *T,int e,int *taller)
{
    if(!*T)
    {
        *T=(BiTree)malloc(sizeof(BiTNode));
        (*T)->data=e;
        (*T)->lchild=(*T)->rchild=NULL;
        (*T)->bf=EH;
        *taller=TRUE;
    }
    //Detect each node in real time
    else
    {
        if(e==(*T)->data)//There is already a value to insert
        {
            *taller=FALSE;
        }
        if(e<(*T)->data)//Go left and insert left subtree
        {
            if(!InsertAVL(&(*T)->lchild,e,taller))//recursion
            {
                return FALSE;//If you find the same, return FALSE
            }
            if(*taller)//We'll test it when we grow tall
            {
                switch ((*T)->bf)
                {
                    case LH://The left subtree is higher than the right subtree, so we have to deal with it
                    LeftBalance(T);//handle
                    *taller=FALSE;
                        break;
                    case EH://It was originally a balance between the left and right subtrees. Now we need to add a left subtree, so the left subtree is higher than the right subtree
                        (*T)->bf=LH;
                        *taller=TRUE;
                        break;
                    case RH://Originally, the right subtree is higher than the left subtree, and then add a left subtree to balance it
                        (*T)->bf=EH;
                        *taller=FALSE;
                        break;
                }
            }
        }
        else//Go right and insert right subtree
        {
            if(!InsertAVL(&(*T)->rchild,e,taller))//recursion
            {
                return FALSE;//If you find the same, return FALSE
            }

            if(*taller)//We'll test it when we grow tall
            {
                switch ((*T)->bf)
                {
                    case LH://Originally, the left subtree is higher than the right subtree, and then add a right subtree to balance it
                        (*T)->bf=EH;
                        *taller=FALSE;
                        break;
                    case EH://It was originally a balance between the left and right subtrees. Now we need to add a right subtree, so the right subtree is higher than the left subtree

                        (*T)->bf=RH;
                        *taller=TRUE;
                        break;
                    case RH://Originally, the right subtree is higher than the left subtree, and then a right subtree is added, which needs to deal with balance
                        RightBalance(T);//handle
                        *taller=FALSE;
                        break;
                }
            }

        }
    }
    return TRUE;
}

int main() {

   int i;
   int a[10]={3,2,1,4,5,6,7,10,9,8};
   BiTree T=NULL;
   Status taller;
   for(i=0;i<10;i++)
   {
       InsertAVL(&T,a[i],&taller);
   }
    return 0;
}

summary

Several corresponding cases in the right balance function

/**
 * Right balance
 * @param T
 */
void RightBalance(BiTree *T)
{
    BiTree R,Rl;
    R=(*T)->rchild;
    switch (R->bf)//T's left child's bf
    {
        case RH://This indicates that R is the same sign as BF of the root node, and the root node can be rotated to the left, and the balance is restored after rotation, so the value of BF should also be modified
            (*T)->bf=R->bf=EH;
            L_Rotate(T);
            break;
        case LH://This indicates that R is opposite to the BF symbol of the root node. Rotate r right and then rotate the root node left
            Rl=R->lchild;
            //It's the switch below. I can't figure it out!!!!
            switch (Rl->bf)
            {
                case RH://
                    (*T)->bf=LH;
                    R->bf=EH;
                    break;
                case EH://I can't find a specific example of this situation
                    (*T)->bf=R->bf=EH;
                    break;
                case LH://I always feel that there is something wrong. Here I can draw my own picture. Suppose I think there is something wrong
                    (*T)->bf=EH;
                    R->bf=RH;
                    break;
            }
            Rl->bf=EH;
            R_Rotate(&(*T)->rchild);//Make symbols the same
            L_Rotate(T);
            break;
    }
}

Several cases in left equilibrium function

/**
 * Left balance
 * @param T
 */
void LeftBalance(BiTree *T)
{
    BiTree L,Lr;
    L=(*T)->lchild;
    switch (L->bf)//T's left child's bf
    {
        case LH://This indicates that L is the same sign as BF of the root node, and the root node can be rotated right, and the balance is restored after rotation, so the value of BF should also be modified
            (*T)->bf=L->bf=EH;
            R_Rotate(T);
            break;
        case RH://This indicates that L is opposite to the BF symbol of the root node. Rotate L left and then rotate the root node right
            Lr=L->rchild;
            //It's the switch below. I can't figure it out!!!!
            switch (Lr->bf)
            {
                case LH://
                    (*T)->bf=RH;
                    L->bf=EH;
                    break;
                case EH://
                    (*T)->bf=L->bf=EH;
                    break;
                case RH://
                    (*T)->bf=EH;
                    L->bf=LH;
                    break;
            }
            Lr->bf=EH;
            L_Rotate(&(*T)->lchild);//Make symbols the same
            R_Rotate(T);
            break;
    }
}

This section is quite brain burning. I finally understand!

m-way search trees

2-3 tree

2-3 trees either have two children. Or no children

2-3 tree with two nodes and three nodes

Insertion principle

In the first case, if it is an empty tree, insert two nodes directly, that is, the root node

In the second case, it is inserted into a two node, and the two nodes become three nodes

The third situation is more complex:

When the inserted leaf is a three node, the leaf parent It is a two node, which inserts new data by expanding its parents
 When the inserted leaf is a three node, the leaf parent It's three nodes. Go find it parent of parent ,have a look parent of parent Is it a two node, can it be extended
 When the inserted leaf is a three node, the leaf parent It's three nodes. Go find it parent of parent ,Tracing back to the root node, if the root node is still three nodes, we need to increase the height of the tree,

Delete principle

Delete leaf node

1, If the leaf to be deleted is an element in three nodes, it is very simple to delete one of the three nodes and turn it into two nodes

For example, in the figure below, you have to delete 6

2, The deleted element is located on the second node

1. First case

The parent of this two node is also a two node, and the other child of this parent is a three node

As shown in the figure below, element 1

2. The second case

This two node parent is two node, and the other child of the two parents is also two node

See element 4 below

3. The third case

The parents of this two node are three nodes

See element 10 in the figure below

3, In the case of full binary tree, all nodes are binary nodes

See element 8 in the figure below

Reduce one layer to three nodes

Delete non leaf nodes

1, The second node is deleted. Children have three nodes

See element 4 below

2, The deleted element has a three node child at three nodes

See element 12 in the figure below

Generally speaking, these deletion principles are relatively simple, but there are many situations to consider

2-3-4 tree

Either two nodes, or three nodes, or four nodes

insert

delete

B tree

nature

Hash table lookup

Construction method

Direct address method

It is to use the key and then linearly calculate the key to obtain the address. It is the direct address method. It is not commonly used

Digital analysis

It is suitable for dealing with large numbers

Square middle method

It is suitable for dealing with the situation that the distribution of keywords is unknown and the number of digits is not very large

Folding method

Do not know the distribution of keywords in advance, which is suitable for the situation with a large number of keywords

Residual tree method

Common methods

Random number method

It is suitable for different keyword lengths

Method for handling hash table conflict

Open address method

Re hash function method

Prepare more hash functions.

Chain address method

Using linked list

Mr. Hou Jie talked about the underlying implementation of STL and used it, like GUC4.9

Public spillover area method

First check the basic table. If the basic table is not found, then find the overflow table

Hash table lookup code implementation

#include <iostream>

using namespace std;
#define  HASHSIZE 12
#define NULLKEY -32768
typedef struct
{
    int *elem;//Base address of data element, dynamically allocating array
    int count;//Number of current data elements

}HashTable;

/**
 * Hash table initialization
 * @param H
 * @return
 */
int InitHahTable(HashTable *H)
{
    H->count=HASHSIZE;
    H->elem=(int *) malloc(HASHSIZE*sizeof (int));
    if(!H->elem)
    {
        return -1;
    }


    for(int i=0;i<HASHSIZE;i++)
    {
        H->elem[i]=NULLKEY;
    }
    return 0;
}

/**
 * Division method 
 * @param key
 * @return
 */
int Hash(int key)
{
    return key% HASHSIZE;
}

/**
 * Insert keyword into hash table
 * @param H
 * @param key
 */
void InsertHash(HashTable *H,int key)
{
    int addr;
    addr= Hash(key);
    while(H->elem[addr]!=NULLKEY)//If it is not empty, a conflict occurs
    {
        //Open addressing 
        addr=(addr+1)%HASHSIZE;
    }
    H->elem[addr]=key;
}

/**
 * Hash table lookup
 * @param H
 * @param key
 * @param addr
 * @return
 */
int SearchHash(HashTable H,int key,int *addr)
{
    *addr= Hash(key);
    while(H.elem[*addr]!=key)
    {
        *addr=(*addr+1)%HASHSIZE;
        if(H.elem[*addr]==NULLKEY|| *addr == Hash(key))//Finding the last key or returning to the origin indicates that this key does not exist
        {
            return -1;
        }
    }
    return 0;

}

/**
 * Test hash table lookup
 */
void test_HashTable()
{
    HashTable H;
    InitHahTable(&H);
    int c;
    int inputKey;
    cout<<"Enter inserted key: (12 individual)"<<endl;
    for(int i=0;i<HASHSIZE;i++)
    {
        cin>>inputKey;
        InsertHash(&H,inputKey);
    }

    cout<<"Please enter the number you want to find:('#'end search) "< < endl;
    cin>>c;
    while(c!=-32768)
    {
        int key=c;
        cout<<key<<": ";
        int add;

        if(SearchHash(H,key,&add))
        {
            cout<<"No such number!"<<endl;
        }
        else
        {
            cout<<"Search succeeded!"<<endl;
            cout<<"Address:"<<add<<endl;
        }
        cout<<"Please enter the number you want to find:('#'end search) "< < endl;
        cin>>c;
    }


}
int main() {
    test_HashTable();

    return 0;
}

Operation results:

Enter inserted key: (12 individual)
1
2
3
4
5
6
7
8
9
10
11
16
 Please enter the number you want to find:('#'end search'
16
16: Search succeeded!
Address: 0
 Please enter the number you want to find:('#'end search'
4
4: Search succeeded!
Address: 4
 Please enter the number you want to find:('#'end search'
12
12: No such number!
Please enter the number you want to find:('#'end search'

Sorting algorithm

Bubble sorting

#include <iostream>
using namespace std;

/**
 * In fact, this is not an authentic bubble sort. The real bubble sort should be two adjacent comparisons
 * This sort is not an adjacent comparison
 * @param k
 * @param n
 */
void BubbleSort(int k[],int n)
{
    int i,j,temp,count1=0,count2=0;
    for(i=0;i<n-1;i++)
    {
        for(j=i+1;j<n;j++)
        {
            count1++;
            if(k[i]>k[j])
            {
                count2++;
                temp=k[j];
                k[j]=k[i];
                k[i]=temp;
            }
        }
    }
    cout<<"How many comparisons were made in total: "<<count1<<"How many moves were made in total: "<<count2<<endl;
}

/**
 * Authentic bubble sorting
 */
void TrueBubbleSort(int k[],int n)
{
    int i,j,temp,count1=0,count2=0;
    for(i=0;i<n-1;i++)
    {
        for(j=n-1;j>i;j--)
        {
            count1++;
            if(k[j-1]>k[j])
            {
                count2++;
                temp=k[j-1];
                k[j-1]=k[j];
                k[j]=temp;
            }
        }
    }
    cout<<"How many comparisons were made in total: "<<count1<<"How many moves were made in total: "<<count2<<endl;
}

/**
 * Authentic bubble sorting plus a little optimization plus a fall
 */
void TrueBubbleSortImproved(int k[],int n)
{
    int i,j,temp,count1=0,count2=0,flag=1;
    for(i=0;i<n-1 && flag;i++)
    {
        for(j=n-1;j>i;j--)
        {
            count1++;
            flag=0;
            if(k[j-1]>k[j])
            {
                count2++;
                temp=k[j-1];
                k[j-1]=k[j];
                k[j]=temp;
                flag=1;
            }
        }
    }
    cout<<"How many comparisons were made in total: "<<count1<<"How many moves were made in total: "<<count2<<endl;
}

int main() {
    int i,a[10]={1,0,2,3,4,5,6,7,8,9};
    //BubbleSort(a,10);
    //TrueBubbleSort(a,10);
    TrueBubbleSortImproved(a,10);// 
    for(int i=0;i<10;i++)
    {
        cout<<a[i];
    }
    cout<<endl;
    return 0;
}

Operation results

Bubble sorting**************************
How many comparisons were made in total: 45 How many moves were made in total: 1
0123456789
 Bubble sorting**************************
Authentic bubble sorting plus flag optimization**************************
How many comparisons were made in total: 17 How many moves were made in total: 1
0123456789
 Authentic bubble sorting plus flag optimization**************************

Select sort

#include <iostream>
using namespace std;

/**
 * Select sort
 * @param a
 * @param n
 */
void ChooseSort(int a[],int n)
{
    int min,temp,count1=0,count2=0;
    for(int i=0;i<n-1;i++)
    {
        min=i;
        for(int j=i+1;j<n;j++)
        {
            count1++;
            if(a[j]<a[min])
            {
                min=j;
            }
        }
        if(min!=i)
        {
            count2++;
            temp=a[min];
            a[min]=a[i];
            a[i]=temp;
        }
    }
    cout<<"How many comparisons were made in total: "<<count1<<"How many moves were made in total: "<<count2<<endl;

}
void testChoose()
{
    cout<<"Select sort**************************"<<endl;
    int a[10]={5,2,6,0,3,9,1,7,4,8};
    ChooseSort(a,10);
    for(int i=0;i<10;i++)
    {
        cout<<a[i];
    }
    cout<<endl;

    cout<<"Select sort**************************"<<endl;
}


/**
 * Authentic bubble sorting plus a little optimization plus a fall
 */
void TrueBubbleSortImproved(int k[],int n)
{
    int i,j,temp,count1=0,count2=0,flag=1;
    for(i=0;i<n-1 && flag;i++)
    {
        for(j=n-1;j>i;j--)
        {
            count1++;
            flag=0;
            if(k[j-1]>k[j])
            {
                count2++;
                temp=k[j-1];
                k[j-1]=k[j];
                k[j]=temp;
                flag=1;
            }
        }
    }
    cout<<"How many comparisons were made in total: "<<count1<<"How many moves were made in total: "<<count2<<endl;
}
void testBubble()
{
    cout<<"Authentic bubble sorting plus flag optimization**************************"<<endl;
    int a[10]={5,2,6,0,3,9,1,7,4,8};
    //BubbleSort(a,10);
    //TrueBubbleSort(a,10);
    TrueBubbleSortImproved(a,10);
    for(int i=0;i<10;i++)
    {
        cout<<a[i];
    }
    cout<<endl;
    cout<<"Authentic bubble sorting plus flag optimization**************************"<<endl;
}
int main() {

    testChoose();
    testBubble();
    return 0;
}

Operation results

Select sort**************************
How many comparisons were made in total: 45 How many moves were made in total: 7
0123456789
 Select sort**************************
Authentic bubble sorting plus flag optimization**************************
How many comparisons were made in total: 39 How many moves were made in total: 17
0123456789
 Authentic bubble sorting plus flag optimization**************************

Direct insert sort

#include <iostream>

using namespace std;

void InsertSort(int a[],int n)
{
    int i,j,temp,count1=0,count2=0;

    for(i=1;i<n;i++)
    {
        count1++;
        if(a[i]<a[i-1])
        {
            temp=a[i];//Set up sentry
            for(j=i-1;a[j]>temp&& j>=0;j--)
            {
                count2++;
                a[j+1]=a[j];
            }
            a[j+1]=temp;

        }
    }
    cout<<"How many comparisons were made in total: "<<count1<<"How many moves were made in total: "<<count2<<endl;
}

void testInsert()
{
    cout<<"Direct insert sort**************************"<<endl;
    int a[10]={5,2,6,0,3,9,1,7,4,8};
    InsertSort(a,10);
    for(int i=0;i<10;i++)
    {
        cout<<a[i];
    }
    cout<<endl;

    cout<<"Direct selection sort**************************"<<endl;
}
int main() {
    testInsert();

    return 0;
}

Operation results

Direct insert sort**************************
How many comparisons were made in total: 9 How many moves were made in total: 17
0123456789
 Direct selection sort**************************

Shell Sort

Before that, the time complexity was O(n2)

The time complexity of hill sorting is:

The interval between two comparisons is different

#include <iostream>

using namespace std;

void ShellSort(int a[],int n)
{
    //{5,2,6,0,3,9,1,7,4,8}
    int i,j,temp,count1=0,count2=0;
    int gap=n;
    do
    {
        gap=gap/3 ;
            for(i=gap;i<n;i++)
            {
                count1++;
                if(a[i]<a[i-gap])
                {
                    temp=a[i];//Set up sentry
                    for(j=i-gap;a[j]>temp&& j>=0;j-=gap)
                    {
                        count2++;
                        a[j+gap]=a[j];
                    }
                    a[j+gap]=temp;

                }
            }
    }while(gap>1);

    cout<<"How many comparisons were made in total: "<<count1<<"How many moves were made in total: "<<count2<<endl;
}

void testShell()
{
    cout<<"Shell Sort **************************"<<endl;
    int a[10]={5,2,6,0,3,9,1,7,4,8};
    ShellSort(a,10);
    for(int i=0;i<10;i++)
    {
        cout<<a[i];
    }
    cout<<endl;

    cout<<"Shell Sort **************************"<<endl;
}
int main() {
    testShell();

    return 0;
}

Operation results

Shell Sort **************************
How many comparisons were made in total: 16 How many moves were made in total: 9
0123456789
 Shell Sort **************************

Heap sort

principle

Improved selection sorting

A complete binary tree is one in which the last layer is satisfied from right to left and the leaves are not vacant

The above figure is a complete binary tree

The figure above is not a complete binary tree

The above figure is a complete binary tree

[external chain picture transferring... (i)

Posted by izzy on Wed, 29 Sep 2021 14:07:18 -0700