Data structure learning notes - linear table

Linear table

primary coverage
2.1 definition and characteristics of linear table
2.2 sequential representation and implementation of linear table
2.3 chain representation and implementation of linear table
2.4 comparison of sequence list and chain list

Supplementary knowledge points: value transfer of parameters
There are two ways to pass parameters:
(1) Value transfer method (parameters are integer, real, character, etc.)
(2) Pass address l parameter is pointer variable l parameter is reference type L parameter is array name

Parameter value passing:

#include <iostream.h> 
void swap(int m,int n) 
{	int temp; 
	temp=m; 
	m=n; 
	n=temp; 
	}
void main() {
	int a,b; 
	cin>>a>>b; 
	swap(a,b); 
	cout<<a<<endl<<b<<endl; 
	}

Can we achieve the expected function?
Changing the value of formal parameter does not change the value of actual parameter!!

Pointer variable passing of parameter:

#include <iostream.h> 
void swap(int *m,int *n) 
{ int temp; 
	temp=*m; 
	*m=*n; 
	*n=temp;
 }
void main()
 {	int a,b,*p1,*p2; 
	 cin>>a>>b;
 	 p1=&a; 
 	 p2=&b; 
	 swap(p1, p2);
  	 cout<<a<<endl<<b<<endl; 
   }

Because the address is actually passed, the values of a and b are exchanged in the output!

Reference type passing of C + + parameters:

#include<iostream.h> 
void main( ) 
{ 	int i=5; 
	int &j=i;
 	i=7; 
 	cout<<"i="<<i<<" j="<<j; 
 }

j is a reference type, representing an alternative name for i
When i value changes, j value also changes, so i=7 j=7 will be output!!

Reference type passing of C + + parameters:

#include <iostream.h> 
void swap(int&m, int&n)
 {	int temp; 
 	temp=m;
  	m=n;
   	n=temp; 
   }
void main() 
{	int a,b;
 	cin>>a>>b; 
 	swap(a,b); 
 	cout<<a<<endl<<b<<endl; 
 }

(1) The effect of passing a reference to a function is the same as passing a pointer, and the parameter change argument changes
(2) Although the pointer parameter can also achieve the effect of using reference, it needs to use the form of "* pointer variable name" repeatedly in the called function for operation, which is easy to produce errors and poor readability of the program; on the other hand, at the call point of the main function, the address of the variable must be used as the argument
(3) The reference type is a parameter, and there is no copy of the parameter in memory. It directly operates on the parameter; while the general variable is a parameter, and the parameter and the parameter occupy different storage units, so the value of the parameter variable is a copy of the parameter variable
Therefore, when the amount of data transferred by parameters is large, the time and space efficiency of using reference is better than that of using general variables to transfer parameters

2.2 definition and characteristics of linear table

1, Definition of linear table
1. Linear table: finite sequence of n (n ≥ 0) data elements, which can be recorded as:
List=(a1,...,ai,ai+1,..., an)
2. Characteristics of linear table:
1) All data elements in the linear table belong to the same data object;
2) The adjacent elements of a linear table are one-to-one ordered even relations, which are reflected in:
a. There is and only one "first" data element;
b. There is and only the first "last element";
c. Except for the first element, each data element has and only has the first precursor;
d. With the exception of the last element, each data element has one and only one successor
3. The number of data elements n(n ≥ 0) in a linear table is called the length of the linear table; when the length of the linear table n=0, it is called the empty table.
4. ai is the i (1 ≤ i ≤ n) data element, i is the bit order of ai in linear table

2, Basic operation of linear table
1. Initial & list
2. Destroy & linear table destroylist
3. Set & empty table clearlist
4. Test empty listempty
5. Find table length listlength
6. Access element GetElem (L, I, & E)
7. Locate element LocateElem(L,e)
8. Insert element & listinsert
9. Delete element & ListDelete
10. Find the antecedent, priorelem (L, cur_e, & pre_e)
11. Find next elem (L, cur ﹣ e, & next ﹣)

1, Basic ideas
1. Using a set of storage units with continuous address to store the data elements in the linear table in turn
2. Features require continuous storage space;
Storage location adjacency is used to represent the precursor and successor relationship of data elements, that is, logical adjacency and physical adjacency

Sequential storage
random access
Loc(i)=Lo+(i-1)*m
Storage density
d = node data / node structure = 1

2, Sequential storage representation of linear tables

Describing order table with one dimensional array

#define MAXSIZE 100 
typedef int ElemType;
typedef struct { 
	ElemType *elem; 
	int length; 	// Number of data elements 
} SqList;		    //Define data type 
	SqList L;      //Defining variables

3, Realization of basic operation of sequence table

Initialization sequence table

Status InitList(SqList &L) 
{ 	L.elem=new ElemType[MAXSIZE]; 
	if (!L.elem) 
		exit (OVERFLOW); 
	L.length=0return OK; 
}//Construct empty order table L

Create order table

Status CreateList(SqList &L, int n ) 
{ 	int i;
 	L.length = n;
  	L.elem = new ElemType[MAXSIZE]; 
  	if (!L.elem) 
  		exit(OVERFLOW)for (i=0; i<n;i++) 
  	 cin>>L.elem[i]return OK; 
    }//Initialize sequence table and assign values

Clear linear table

void ClearList(SqList &L) 
{ 
	L.length=0; //Set the length of the linear table to 0 
}

Destroy linear table

void DestroyList(SqList &L) 
{ 
	if (L.elem) 
		delete L.elem; //Free up storage space 
}

Lookup of order table

① Search by bit order and return element value;
② Find by value: return bit order; otherwise: return 0

There are two ways to represent a sequence table: array representation and pointer representation

Find in bit order

//Array method
int GetElem(SqList L, int i, ElemType &e) 
{ // i stands for bit order 
	if (i<1||i>L.length) 
		return ERROR; 
	e=L.elem[i-1];
	return 0; 
} //T(n)=O(1)

//Pointer method
int GetElem(SqList L, int i, ElemType &e) 
{ // i stands for bit order 
	if (i<1||i>L.length) 
		return ERROR; 
	ElemType *p=&L.elem[i-1]; 
	e=*p;
	return 0; 
} //T(n)=O(1)

Search by value

//Array method
int LocateElem(SqList L, ElemType e)  
{ 	int i; 
	for (i=0;i<L.length;i++) 
		if (L.elem[i]==e) 
			return i+1; 
	return 0; //i for subscript 
}

//Pointer method
int LocateElem(SqList L, ElemType e)  
{ 	int i=1; 
	ElemType *p; 
	p=L.elem; //p=&L.elem[0]; 
	while (i<=L.length&&e!=*p++) 
		++i; 
	if (i<=L.length) 
		return i; 
	else 
		return 0}

Average search length

The average number of successful searches (pi is the search probability of each item)

If the search probability is equal, then

Failed to find, worst case comparison n times

Insert elements in bit order
Linear table: (a1 ai-1,ai,... , an)
Insert element E: (a1 ,ai-1,e,ai,… , an)
Finish:
(1) Judge whether the insertion position is legal;
(2) If it is full, ERROR will be returned;
(3) Put the i n elements move backward one by one;
(4) Insert the new element e at position i;
(5) Table length plus 1, return status information

Status ListInsert(SqList &L,int i,ElemType e) 
{ //Insert a new element before the i-th element of the order table 
	if (i<1 || i>L.length+1) //Insertion position i is too small or too large
		return ERROR; 
	if (L.length==MAXSIZE) //Linear table full
		return ERROR; 
	for (j=L.length-1; j>=i-1; j--) 
		L.elem[j+1]= L.elem[j]; 
	L.elem[i-1]=e; 
	++L.length; 
	return OK; 
}

Delete elements in bit order
Linear table: (a1 ,ai-1,ai,ai+1,… , an)
Delete element AI: (a1 ,ai-1, ai+1,… , an)
Finish:
(1) Judge whether the deletion position is legal;
(2) Judge whether the linear table is empty;
(3) Add i+1 n elements move forward one bit in turn;
(4) Table length minus 1, return success status value

Status ListDelete(SqList &L,int i) 
{ //Delete the i-th element in the order table 
	if (i<1||i>L.length) //Judge whether the position of i is legal
		return ERROR; // i is a sequence. 
	if (L.length==0) 
		return ERROR; 
	for (j=i;j<=L.length-1;j++) 
		L.elem[j-1]=L.elem[j]; 
	--L.length; 
	return OK; 
} 

Insert and delete algorithm time analysis
(1) Time complexity is measured by the number of moving nodes
(2) Insert element
Best: i=n+1, the number of moves is 0
Worst case: i=1, n moves
Average: in the case of equal probability, the average number of moves is n/2

(3) Delete element
Best: i=n, 0 moves
Worst case: i=1, n-1 moves
Average: average number of moves (n-1)/2 under equal probability

2.3 chain representation and implementation of linear table
1, Definition and representation of single chain table
1. Basic ideas
A set of arbitrary storage units (continuous or discrete) is used to store the data elements of a linear table, and the storage location of its subsequent elements is determined by the pointer of each data element
(1) The storage image of a data element is called a node: (data domain, pointer domain)
(2) Linked storage structure: n nodes in a linear list are linked into a linked list
(3) The list with only one pointer field in each node is called single chain list, the list with two pointer fields is called two-way list, and the linked list with the head and tail is called circular list

2. Storage structure of single chain table

Typedef struct LNode 
{ 	ElemType data;      //Data field of node
	Struct LNode *next; //Pointer field of node 
} LNode, *LinkList; 	 //LinkList is a pointer type to LNode

Equivalent to: Typedef LNode *LinkList;
Definition: LinkList L; (head pointer L) / / or LNode *p; (node pointer p)
Use: L - > next, or P - > data, etc

3. Single chain representation of leading node

First element node: the node storing the first data element a1
Head node: the additional node pointing to the head node before the head node
Head pointer: pointer to the first node in the list

Find the length of single chain table
[algorithm steps]
(1) Sequential scanning, synchronous counting
(2) Pay attention to the match of initial value and cycle condition
T(n)=O(n)
[algorithm description]

//Law 1
int Length(LinkList L) 
{ 	LNode *p=L->next; 
	int len=1; 
	while (p!=NULL) 
	{ 
		p=p->next; 
		len++; 
	} 
	return len; 
}

//Law 2
void Length(LinkList &L)
 {
  	LNode *p=L; 
  	int len=0; 
  	while (p->next) 
 	 { 
 		 p=p->next; 
  		len++; 
  	} 
 	 L->data=len; 
  }

Value by bit order

[algorithm steps]
(1) Pointer p points to the initial node, and the initial value of counter j is 1
(2) When p is not empty or serial number i is not reached: scan along the chain and count synchronously
(3) When exiting the loop, if the pointer p is null or the counter J is greater than the bit sequence i, it means that the bit sequence i value is illegal, and ERROR will be returned if the value fails; otherwise, the value succeeds, j==i, and the node p refers to is the node with the bit sequence i

[algorithm description]

Status GetElem(LinkList L, int i, ElemType &e) 
{ 	LinkList p=L->next; 
	int j=1// p points to the initial node, j is the counter 
	while (p&&j<i) 
	{ 
		p=p->next;
		++j; 
	} 
	if (!p || j>i) 
		return ERROR; // i> N or I ≤ 0, illegal
	 e=p->data; // Take the value of node i 
 	return OK; 
 }


T(n)=O(n)

Find by value return pointer

[algorithm steps]
(1) Pointer p points to the initial node
(2) If P is not empty, and the node value p refers to is not equal to the given value e, then cycle: scan along the chain
(3) When exiting the loop, the pointer p is returned. When the search succeeds, p is the node address value; when the search fails, p is NULL

[algorithm description]

LNode *LocateElem(LinkList L, ElemType e) 
{ 	LinkList p=L->next ; // Single chain table with leading node 
	while (p&&p->data!=e) 
		p=p->next; 
	return p; 
}

T(n)=O(n)

Find by value return bit order

[algorithm steps]
(1) Pointer p points to the initial node, and the initial value of counter i is 1
(2) If P is not empty, and the node value p refers to is not equal to the given value e, then cycle execution: scan along the chain, synchronous counting
(3) When exiting the loop, if the pointer p is null, it will return 0, otherwise it will return bit sequence i

[algorithm description]

int FindElem(LinkList L, ElemType e) 
{ 	LinkList p=L->next ; 
	int i=1; 
	while (p&&p->data!=e)
 	{ 
 		p=p->next;
 		i++} 
 	if (!p) 
 		return 0else 
 		return i;
  }

T(n)=O(n)

Insertion element


[algorithm steps]

s->next=p->next; 
p->next=s;

Note: here two statements cannot exchange order. Once the order is exchanged, ai+1 cannot be found after executing p - > next = s first!

[algorithm description]

Status ListInsert(LinkList &L,int i, ElemType e) 
{ 	LinkList p=L,s; 
	int j=0while (p&&j<i-1) 
	{ 
		p=p->next; 
		++j; 
	} //p points to the i-1 node 
	if (!p||j>i-1) 
		return ERROR;// I>n+1 or i<1 
	s=new LNode; 
	s->data=e; 
	s->next=p->next; 
	p->next=s; 
	return OK;
}

T(n)=O(n)

Delete elements


[algorithm steps]

	q=p->next;
	p->next=q->next;
	delete q;

[algorithm description]

Status ListDelete(LinkList &L, int i) 
{
 	LinkList p=L,q; 
 	int j=0while (p->next&&j<i-1) 
 	{ 
 		p=p->next;
 		++j;
 	} // p - > next is the node to be deleted, and p points to the i-1 node 
 	if (!(p->next)||j>i-1)
  		return ERROR; //I>n or i<1 
  	q=p->next; 
  	p->next=q->next; 
  	delete q; 
  	return OK;
  }

T(n)=O(n)

Create a single chain table

1) Insert a new node in the header of the linked list, the order of the nodes is opposite to the order of the input
2) The post insertion method builds the table, inserts the new node at the end of the list, and adds a tail pointer last, so that it always points to the tail node of the current list

Creating single chain table by forward interpolation

[algorithm steps]

1) Create an "empty table";
2) Input the data element an and set up the node;
3) Enter data element an-1, insert before an
4) And so on until a1 is entered

[algorithm description]

void CreateList_H(LinkList &L, int n) 
{ 	LinkList p; 
	L=new LNode; 
	L->next=NULLfor (int i=n; i>0; --i) 
	{ 
		p=new LNode;
		cin>>p->data; 
		p->next = L->next; 
		L->next=p; 
	} 
}

T(n)=O(n)

Creating a single chain table by post interpolation

[algorithm steps]

1) Create an "empty table";
2) Input the data element a1 to establish the node;
3) Enter data element a2, insert after a1
4) And so on until an is entered

[algorithm description]

void CreateList_R(LinkList &L, int n) 
{ 	LinkList p,last=L; 
	L=new LNode; 
	L->next=NULLfor (i=0; i<n;++i) 
	{ 
		p=new LNode; 
		cin>>p->data;
		p->next=NULL; 
		last->next=p; 
		last=p; 
	}  
}

T(n)=O(n)

3, Circular list

1. Basic ideas
Circular list is a kind of linked list with head and tail: the next pointer of the last node is not NULL, but points to the header node

2. Completely consistent with the representation of single chain table

	Typedef struct LNode 
	{ 	ElemType data ; 
		Struct LNode *next ;
 	} LNode, *LinkList ;

3. Difference from single chain table: embodied in operation
(1) Different control of cycle conditions
Single chain table: p!=NULL; P - > next! = null;
Circular list: p!=L; P - > next! = L;
(2) Different starting points of traversal
Single chain table: L
Circular list: L or p

Merge two single chain tables

	p=La; 
	while (p->next) 
		p=p->next;// p points to the last node 
	p->next = Lb->next; 
	delete Lb;

T(n)=O(La.length)

Merge two circular lists

	p=La; 
	while (p->next!=La) 
		p=p->next; 
	p->next=Lb->next; // Lb to end of La 
	p=p->next; 
	while (p->next!=Lb) 
		p=p->next; 
	p->next=La; // Modify tail pointer
	delete Lb;

T(n) = O(La.length+Lb.length)

4, Double linked list

1. Bi directional linked list is a linear linked list that can traverse both the precursor and the successor directions

Two way linked list usually adopts the form of cyclic linked list with leading node

2. Representation of bidirectional (cyclic) linked list

Typedef struct DuLNode 
{ 	ElemType data; 
	struct DuLNode *prior; 
	struct DuLNode *next; 
} DuLNode, *DuLinkList;


It should be noted that:

p==p->prior->next ==p->next->prior

Insertion of two way circular list

(1) s->next = p->next; 
(2) p->next = s; 
(3) s->next->prior = s; 
(4) s->prior = p;

T(n)=O(n)

Deletion of two way circular list

(1) p->next=p->next->next; 
(2) p->next->prior=p;

[algorithm description]

Status ListDele_Dul(DuLinkList &L,int i,ElemType &e) 
{ 	DuLNode *p=L->next; 
	int j=1; 
	while (p&&j<i) 
	{ 
		p=p->next;
		j++; 
	} // p points to the ith node 
	if (!p||j>i) 
		return ERROR; 
	e=p->data; 
	p->prior->next=p->next; 
	p->next->prior=p->prior; 
	delete p; 
	return OK; 
}// ListDele_Dul

T(n)=O(n)

Usage of linear table

1, Merging of linear tables

[algorithm steps]
1) Obtain LA table length m and LB table length n respectively
2) Starting with the first element in LB, loop through the following:
① Find the i(1 ≤ i ≤ n) data element e from LB
② Find element E in LA, and insert e to the end of table La if it does not exist

[algorithm description]

void MergeList(List &LA,List LB) 
{ //Insert all data elements in linear table LB but not in LA into LA 
	m=ListLength(LA); 
	n=ListLength(LB); //Find the length of linear table 
	for(i=1;i<=n;i++) 
	{ 	
		GetElem(LB,i,e); //Assign the ith data element in LB to e 
		if(!LocateElem(LA,e)) 
			ListInsert(LA,e); 
	} 
}

2, Merge of ordered tables

1. Merge of ordered tables

1) Create an empty table with a length of m+n
2) Pointer pc initialization, pointing to the first element of LC
3) Initialization of pointers pa and pb, pointing to the first element of LA and LB respectively
4) When the pointers pa and pb do not reach the corresponding tail, the element values of pa and pb are compared in turn, and the nodes with smaller element values are extracted from LA or LB and inserted into LC tail
5) If pb reaches the end of LB, insert the remaining elements of LA into the last of LC in turn
6) If pa reaches the end of LA table, insert the remaining elements of LB into the last of LC in turn

void MergeList_Sq(SqList LA,SqList LB,SqList &LC) 
{ 
	int *pa=LA.elem,*pbLB.elem,*pc,*pa_last,*pb_last; 
	LC.length=LA.length+LB.length; 
	LC.elem=new ElemType[LC.length]; 
	pc=LC.elem; 
	pa_last=LA.elem+LA.length-1; 
	pb_last=LB.elem+LB.length-1; 
	while(pa<=pa_last && pb<=pb_last) 
	{ 
		if(*pa<=*pb) 
			*pc++=*pa++; 
		else 
			*pc++=*pb++; 
	} 
	while(pa<=pa_last) 
		*pc++=*pa++; 
	while(pb<=pb_last) 
		*pc++=*pb++;
 }

2. Merge of chain ordered list
1) Initialization of pointers pa and pb, pointing to the first node of LA and LB respectively
2) The node value of LC is the header node of LA
3) Pointer pc initialization, pointing to LC header node
4) When the pointers pa and pb do not reach the corresponding tail, the element values of pa and pb are compared in turn, and the nodes with smaller element values are extracted from LA or LB and inserted into LC tail
5) Insert the remaining nodes of non empty table at the end of LC
6) Release the head node of LB

void MergeList_L(LinkList &LA,LinkList &LB,LinkList &LC) 
{ 
	LinkList pa=LA->next,pb=LB->next,pc; 
	LC=LA; pc=LC; 
	while(pa && pb) 
	{ 
		if(pa->data <= pb->data) 
		{ 
			pc->next=pa; 
			pc=pa; 
			pa=pa->next; 
		} 
		else 
		{ 
			pc->next=pb; 
			pc=pb; 
			pb=pb->next; 
		} 
	}
	pc->next=pa?pa:pb; 
	delete LB; 
} //MergeList_L()
Published 2 original articles, praised 0 and visited 17
Private letter follow

Posted on Sun, 09 Feb 2020 05:13:37 -0500 by beesgirl713