[LeetCode]-622. Zirkuläre Warteschlange entwerfen

Inhaltsverzeichnis

662. Zirkuläre Warteschlange entwerfen

Thema

Ideen

Code


662. Zirkuläre Warteschlange entwerfen

622. Design Circular Queue – LeetCodeicon-default.png?t=N7T8https://leetcode.cn/problems/design-circular-queue/

Thema

Entwerfen Sie Ihre Implementierung einer kreisförmigen Warteschlange. Eine kreisförmige Warteschlange ist eine lineare Datenstruktur, deren Funktionsweise auf dem FIFO-Prinzip (First In, First Out) basiert und bei der das Ende der Warteschlange nach dem Kopf der Warteschlange verbunden wird, um eine Schleife zu bilden. Er wird auch „Ringpuffer“ genannt.

Ein Vorteil von zirkulären Warteschlangen besteht darin, dass wir zuvor genutzten Platz in dieser Warteschlange nutzen können. In einer normalen Warteschlange können wir, sobald eine Warteschlange voll ist, das nächste Element nicht einfügen, selbst wenn am Anfang der Warteschlange noch Platz ist. Mithilfe einer zirkulären Warteschlange können wir diesen Platz jedoch zum Speichern neuer Werte nutzen.

Ihre Implementierung sollte die folgenden Vorgänge unterstützen:

  • MyCircularQueue(k): Konstruktor, setze die Warteschlangenlänge auf k.
  • Front: Holen Sie sich das Element vom Kopf der Warteschlange. Wenn die Warteschlange leer ist, wird -1 zurückgegeben.
  • Rear: Holen Sie sich das Endelement der Warteschlange. Wenn die Warteschlange leer ist, wird -1 zurückgegeben.
  • enQueue(value): Ein Element in die zirkuläre Warteschlange einfügen. Gibt true zurück, wenn das Einfügen erfolgreich war.
  • deQueue(): Ein Element aus der zirkulären Warteschlange entfernen. Gibt true zurück, wenn der Löschvorgang erfolgreich war.
  • isEmpty(): Überprüfen Sie, ob die Ringwarteschlange leer ist.
  • isFull(): Überprüfen Sie, ob die Ringwarteschlange voll ist.

Beispiel:

Ideen

Öffnen Sie ein Array der Größe k+1, das k gültige Elemente speichern kann. Der Kopf der Warteschlange vorne und die Rückseite der Warteschlange hinten sind die Array-Indizes. Die Positionen vorne und hinten werden beim Einfügen und Löschen von Daten verschoben. Wenn die Wenn das Ende des Arrays überschritten wird, kehrt es zur Kopfposition des Arrays zurück. Bilden Sie eine Schleife, um den Effekt einer kreisförmigen Warteschlange zu erzielen.

Die Implementierung einer zirkulären Warteschlange hat folgende Auswirkungen:

Schwierigkeit 1:

hinten fügt Daten am Ende des Arrays ein:Wenn hinten das Ende des Arrays erreicht, müssen Daten in hinten eingefügt werden und hinten muss eine Schleife zurück zum Kopf des Arrays erfolgen Array statt direkt Rear++ Das war's.

Lösung:

  • Modulo-Idee: Rear++ moduliert die Array-Länge k+1 und kehrt nach Überschreiten des Array-Endes zum Array-Kopf zurück, wie unten gezeigt: 

Schwierigkeit 2:

Daten löschen, wenn sich Front am Ende des Arrays befindet:Wenn sich Front gerade am Ende des Arrays befindet, müssen Sie Elemente vom Anfang der Warteschlange löschen und Die Vorderseite wird über das Ende des Arrays hinaus verschoben.

Lösung:

  • Modulo-Idee: Wenn Front das Ende des Arrays überschreitet, modulieren Sie die Array-Länge k+1, Front kehrt zum Kopf des Arrays zurück, wie unten gezeigt:

Schwierigkeit 3:

Rufen Sie das Endelement der Warteschlange ab: Wenn sich hinten an der Position des Array-Index 0 befindet, befindet sich hinten an der Position von -1 bis -1 und das Endelement befindet sich an der Position von -1 bis -1 an der Position des Endes des Arrays.

Lösung:

  • Fügen Sie eine if-Anweisung hinzu. Wenn sich hinten an der Position des Index 0 befindet, nehmen Sie die Position des Endelements der Warteschlange als Index k+1.
  • Modulo-Idee: Beim Entfernen des Indexes (rear+(k+1)-1)%(k+1) wie unten gezeigt:

Code

(Die folgenden Funktionen umfassen aufzurufende Funktionen wie Sounding und Full Sounding. Diese Funktionen sollten früher platziert werden.Zuerst deklarieren und dann verwenden

typedef struct {
    int* a;//起始地址
    int front;//数组下标
    int rear;//数组下标
    int k;//有效数据个数
} MyCircularQueue;


//构造器
MyCircularQueue* myCircularQueueCreate(int k) {
    //结构体开辟空间
    MyCircularQueue* obj=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    //数组开辟空间,多开辟一个可区分满和空
    obj->a=(int*)malloc(sizeof(int)*(k+1));
    //开始是空的状态
    obj->front=obj->rear=0;
    //传入的数(有效个数)给给k
    obj->k=k;

    return obj;
}
//探空和探满尽量位置往前放
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    return obj->front==obj->rear;
}
bool myCircularQueueIsFull(MyCircularQueue* obj) {
    return (obj->rear+1)%(obj->k+1)==(obj->front);
}

//插入一个元素 成功返回真
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    //判断是否满
    if(myCircularQueueIsFull(obj))
        return false;
    //插入rear位置
    obj->a[obj->rear]=value;
    obj->rear++;
    //模上一个数组的长度,rear超过到数组尾可以循环回到数组头
    obj->rear%=(obj->k+1);
    return true;
}
//删除
bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    //判断是否为空
    if(myCircularQueueIsEmpty(obj))
        return false;

    //队头front往后移 ++front
    ++obj->front;
    //取模可在超过队尾时回到队头,取模不影响中间的移动
    obj->front%=(obj->k+1);
    return true;
}

//取队头元素
int myCircularQueueFront(MyCircularQueue* obj) {
    //探空
    if(myCircularQueueIsEmpty(obj))
        return -1;
    else
        return obj->a[obj->front];
}

int myCircularQueueRear(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
        return -1;
    else
        //模上k+1  rear+(k+1)-1 % (k+1)
        return obj->a[(obj->rear+obj->k) % (obj->k+1)];
}


void myCircularQueueFree(MyCircularQueue* obj) {
    free(obj->a);
    free(obj);
}

Supongo que te gusta

Origin blog.csdn.net/m0_64476561/article/details/134348913
Recomendado
Clasificación