Sequence table
Sequence table commonly used are static sequence table and dynamic sequence table Common dynamic sequence table
The code implements the sequence table, including the pushhead pushback poppead pop back of the sequence table, which can be combined with the previous address book:
Exercise remove the array of duplicate elements from the array in place
int removeElement(int* nums, int numsSize, int val){ int j=0; int count=numsSize; for(int i=0;i<numsSize;i++) { if(nums[i]!=val) { nums[j]=nums[i]; j++; } else { ; } } return j; }
Sequence table function implementation code void SeqListPrint(SL* ps) { for (int i = 0; i < ps->size; ++i) { printf("%d ", ps->a[i]); } printf("\n"); } void SeqListInit(SL* ps) { ps->a = NULL; ps->size = ps->capacity = 0; } void SeqListDestory(SL* ps) { free(ps->a); ps->a = NULL; ps->capacity = ps->size = 0; } void SeqListCheckCapacity(SL* ps) { // If there is no space or insufficient space, we will expand the capacity if (ps->size == ps->capacity) { int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2; SLDataType* tmp = (SLDataType*)realloc(ps->a, newcapacity*sizeof(SLDataType)); if (tmp == NULL) { printf("realloc fail\n"); exit(-1); } ps->a = tmp; ps->capacity = newcapacity; } } void SeqListPushBack(SL* ps, SLDataType x) { /*SeqListCheckCapacity(ps); ps->a[ps->size] = x; ps->size++;*/ SeqListInsert(ps, ps->size, x); } void SeqListPopBack(SL* ps) { // Gentle treatment //if (ps->size > 0) //{ // //ps->a[ps->size - 1] = 0; // ps->size--; //} // Treatment of violence /*assert(ps->size > 0); ps->size--;*/ SeqListErase(ps, ps->size-1); } void SeqListPushFront(SL* ps, SLDataType x) { //SeqListCheckCapacity(ps); Mobile data //int end = ps->size - 1; //while (end >= 0) //{ // ps->a[end + 1] = ps->a[end]; // --end; //} //ps->a[0] = x; //ps->size++; SeqListInsert(ps, 0, x); } void SeqListPopFront(SL* ps) { assert(ps->size > 0); // Mobile data //int begin = 0; //while (begin < ps->size-1) //{ // ps->a[begin] = ps->a[begin+1]; // ++ begin; //} //int begin = 1; //while (begin < ps->size) //{ // ps->a[begin-1] = ps->a[begin]; // ++begin; //} //ps->size--; SeqListErase(ps, 0); } int SeqListFind(SL* ps, SLDataType x) { for (int i = 0; i < ps->size; i++) { if (ps->a[i] == x) { return i; } } return -1; } // Specify pos subscript position insertion void SeqListInsert(SL* ps, int pos, SLDataType x) { // Gentle handling /*if (pos > ps->size || pos < 0) { printf("pos invalid\n"); return; }*/ // A rough way assert(pos >= 0 && pos <= ps->size); SeqListCheckCapacity(ps); // Mobile data int end = ps->size - 1; while (end >= pos) { ps->a[end + 1] = ps->a[end]; --end; } ps->a[pos] = x; ps->size++; } // Delete pos location data void SeqListErase(SL* ps, int pos) { assert(pos >= 0 && pos < ps->size); int begin = pos + 1; while (begin < ps->size) { ps->a[begin - 1] = ps->a[begin]; ++begin; } ps->size--; }
Linked list research headless one-way acyclic linked list and leading two-way circular linked list:
SListNode* BuySListNode(SLTDateType x); // Single linked list printing void SListPrint(SListNode* plist); // Single chain table tail insertion void SListPushBack(SListNode** pplist, SLTDateType x); // Header insertion of single linked list void SListPushFront(SListNode** pplist, SLTDateType x); // Tail deletion of single linked list void SListPopBack(SListNode** pplist); // Single chain header deletion void SListPopFront(SListNode** pplist); // Single linked list lookup SListNode* SListFind(SListNode* plist, SLTDateType x); // The single linked list inserts an x after the pos position // Analyze and think why not insert before the pos position? void SListInsertAfter(SListNode* pos, SLTDateType x); // Value after deleting pos position in single linked list // Analyze and think why not delete the pos location? void SListEraseAfter(SListNode* pos);
Differences between sequential list and linked list:
storage space Random access to insert or delete elements anywhere insert Application scenario Cache utilization
Stack: a special linear table that allows insertion and deletion of elements only at a fixed end. One end for data insertion and deletion is called the top of the stack, and the other end is called the bottom of the stack. The data elements in the stack follow the principle of Last In First Out LIFO (Last In First Out). Stack pressing: the stack insertion operation is called stack entering / stack pressing / stack entering, and the input data is at the top of the stack. Stack out: stack deletion is called stack out. The output data is also at the top of the stack.
Stack can generally be implemented by array or linked list. Relatively speaking, the structure of array is better. Because the cost of inserting data on the tail of the array is relatively small.
Queue: a special linear table that only allows data insertion at one end and data deletion at the other end. The queue has a first in first out FIFO(First In First Out) in the queue: the end of the queue where the insertion operation is performed is called the end of the queue; the end of the queue where the deletion operation is performed is called the head of the queue
The queue can also be implemented in the structure of array and linked list. It is better to use the structure of linked list, because if the structure of array is used, the efficiency will be relatively low.
Queue function code implementation
void QueueInit(Queue* pq) { assert(pq); pq->head = NULL; pq->tail = NULL; } void QueueDestroy(Queue* pq) { assert(pq); QueueNode* cur = pq->head; while (cur != NULL) { QueueNode* next = cur->next; free(cur); cur = next; } pq->head = pq->tail = NULL; } void QueuePush(Queue* pq, QDataType x)//Tail insertion { assert(pq); QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode)); newnode->data = x; newnode->next = NULL; if (pq->head == NULL) { pq->head = pq->tail = newnode; } else { pq->tail->next = newnode; pq->tail = newnode; } } void QueuePop(Queue* pq)//Header deletion { assert(pq); //if (pq->head == NULL) // return; assert(!QueueEmpty(pq)); QueueNode* next = pq->head->next; free(pq->head); pq->head = next; if (pq->head == NULL) { pq->tail = NULL; } } QDataType QueueFront(Queue pq)//Return header data { assert(pq); assert(!QueueEmpty(pq)); return pq.head->data; } QDataType QueueBack(Queue* pq)//Return tail data { assert(pq); assert(!QueueEmpty(pq)); return pq->tail->data; } int QueueSize(Queue* pq) //Calculated quantity { assert(pq); int n = 0; QueueNode* cur = pq->head; while (cur) { ++n; cur = cur->next; } return n; } bool QueueEmpty(Queue* pq) //Judge whether it is empty { assert(pq); return pq->head == NULL; }