2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
So wie wir einige funktionale Schnittstellen für einfach verknüpfte Listen schreiben, schreiben wir zunächst einige Schnittstellen für doppelt verknüpfte Listen, um uns mit dem Hauptgerüst vertraut zu machen:
#enthalten<stdio.h>
#enthalten<stdlib.h>
Typdefinition int LDataType;
//Der Knoten der zirkulär verknüpften Liste mit Zwei-Wege-Kopf
Typdefinitionsstruktur ListNode{
LDataTyp _data;
//Zeigen Sie auf die Startposition des nächsten Knotens
Struktur ListNode* _next;
//Zeigen Sie auf die Startposition des vorherigen Knotens
Struktur LIst* _prev;
}Listenknoten;
//Zirkuläre verknüpfte Liste mit Zwei-Wege-Kopf
Typdefinitionsstruktur List{
Struktur ListNode* _head;
}Aufführen;
Struktur ListNode* erstelleListNode(LDataType val){
Struktur ListNode* Knoten = (Struktur ListNode*)malloc(Größe von(Struktur ListNode));
Knoten->_Daten = Wert;
Knoten->_next = NULL;
Knoten->_vorheriger = NULL;
}
void ListInit(Liste*lst){
//Leere verknüpfte Liste
lst->_head = Listenknoten erstellen(0);
lst->_head->_nächstes = lst->_head->_vorheriges = lst->_head;
}
//Endeinfügung O(1) //Daten vor dem Kopf einfügen ListInsert(lst, lst->_head, val);
void ListpushBack(List* lst, LDataType val){
wenn (lst == NULL){
zurückkehren;
Struktur ListNode* last = lst->_head->_prev;
Struktur ListNode* neuerNode = erstelleListNode(Wert);
//_head ... letzter neuer Knoten
letzter->_nächster = neuer Knoten;
neuer Knoten->_vorheriger = letzter;
neuer Knoten->_next = lst->_head;
lst->_head->_prev = neuer Knoten;
}
}
//Tail delete://Löschen Sie den vorherigen Knoten des Kopfes ListErase(lst, lst->_head->_prev);
void ListPopBack(Liste*lst){
wenn (lst == NULL)
zurückkehren;
//Bestimmen Sie, ob die verknüpfte Liste leer ist
wenn (lst->_head->_next == lst->_head)
zurückkehren;
Struktur ListNode* last = lst->_head->_prev;
Struktur ListNode* vorherige = letzte->_vorherige;
frei (letzte);
lst->_head->_prev = vorherige;
vorheriges->_nächstes = letztes->_Kopf;
}
void druckeListe(Liste*lst){
Struktur ListNode* aktuell = lst->_head->_next;
während (aktuell != lst->_head){
printf("%d", aktuell->_Daten);
aktuell = aktuell->_nächstes;
}
printf("n");
}
//Kopf einfügen//ListInsert(lst,lst->_head->_next,val);
void ListPushFront(List* lst, LDataType val){
wenn (lst == NULL)
zurückkehren;
Struktur ListNode*nächstes = lst->_head->_next;
Struktur ListNode* neuerNode = erstelleListNode(Wert);
//_head, neuer Knoten, nächster
lst->_head->_next = neuer Knoten;
neuer Knoten->_prev = lst->_head;
neuerKnoten->_next = nächster;
nächster->_vorheriger = neuer Knoten;
}
//Header löschen//ListErase(lst,lst->_head->_next);
void ListPopFront(Liste*lst){
wenn (lst == NULL || lst->_head == lst->_head)
zurückkehren;
Struktur ListNode*nächstes = lst->_head->_next;
Struktur ListNode* nextnext = next->_next;
nächstesnächstes->_vorheriges = nächstes->_nächstes;
lst->_head->_next = nächsterNächster;
frei (weiter);
}
void ListErase(List*lst, struct ListNode*Knoten){
//Kopfknoten kann nicht gelöscht werden
wenn (lst == NULL || lst->_head == Knoten)
zurückkehren;
//vorheriger, Knoten, nächster
Struktur ListNode* prev = node->_prev;
Struktur ListNode*nächster = node->_next;
vorheriges->_nächstes = nächstes;
nächstes->_vorherige = vorige;
frei(Knoten);
}
void ListInsert(List* lst, struct ListNode* node, LDataType val){
wenn (lst == NULL)
zurückkehren;
Struktur ListNode* prev = node->_prev;
Struktur ListNode* neuerNode = erstelleListNode(Wert);
//vorheriger neuer Knoten
vorherige->_nächstes = neuer Knoten;
neuerKnoten->_vorheriger = voriger;
neuerKnoten->_next = Knoten;
Knoten->_vorheriger = neuer Knoten;
}
//zerstören
ListDestoty(Liste*lst){
wenn (lst){
wenn (lst->_head){
Struktur ListNode* aktuell = lst->_head->_next;
während (aktuell != lst->_head){
Struktur ListNode*nächstes = cut->_next;
frei (aktuell);
aktuell = nächstes;
}
frei(lst->_head);
}
}
}
ungültiger Test () {
Liste lst;
ListeInit(&lst);
ListPushFront(&lst, 5);
Liste drucken(&lst);
: ListPushFront(&lst, 1);
Liste drucken(&lst);
: ListPushFront(&lst, 2);
Liste drucken(&lst);
ListPushFront(&lst, 3);
Liste drucken(&lst);
ListPushFront(&lst, 4);
Liste drucken(&lst);
ListPopFront(&lst);
Liste drucken(&lst);
ListPopFront(&lst);
Liste drucken(&lst);
ListPopFront(&lst);
Liste drucken(&lst);
/*ListPopBack(&lst);
Liste drucken(&lst);
ListPopBack(&lst);
Liste drucken(&lst);
ListPopBack(&lst);
Liste drucken(&lst);
ListPopBack(&lst);
Liste drucken(&lst);*/
}
int main(){
prüfen();
system("pause");
gebe 0 zurück;
}
Der Unterschied und Zusammenhang zwischen Sequenzliste und verknüpfter Liste:
Vor- und Nachteile der Sequenztabelle: Ausgezeichnet: Der Speicherplatz ist kontinuierlich, unterstützt Direktzugriff, hat eine hohe Speicherplatzauslastung und verursacht wahrscheinlich keine Speicherfragmentierung und weist eine hohe Effizienz beim Einfügen und Löschen von Enden auf.
Nachteile: 1. Der zeitliche Aufwand für das Einfügen und Löschen des mittleren oder vorderen Teils beträgt O(N) 2. Die Kosten für die Kapazitätserweiterung sind relativ hoch: Beantragen Sie eine Kopiefreigabe
Vor- und Nachteile verknüpfter Listen (geführte bidirektionale, zufällig verknüpfte Listen)
Vorteile: 1. Die zeitliche Komplexität des Einfügens und Löschens an einer beliebigen Position beträgt O(1). 2. Es gibt kein Problem der Kapazitätserweiterung. Durch das Einfügen einer einzigen Position wird ein Leerzeichen geöffnet, und die Effizienz des Einfügens und Löschens an einer beliebigen Position ist hoch
Nachteile: Es wird in Knoteneinheiten gespeichert, unterstützt keinen Direktzugriff und eine geringe Speicherplatznutzung kann leicht zu Speicherfragmentierung führen.
Stapel und Warteschlangen
Stapel: Eine spezielle lineare Liste, die nur das Einfügen und Löschen von Elementen an einem Ende zulässt. Das Ende, an dem Daten eingefügt und gelöscht werden, wird als oberes Ende des Stapels und das andere Ende als unterstes Ende des Stapels bezeichnet Im Stapel folgt das LIFO-Prinzip (Last In First Out).
Schieben des Stapels: Der Einfügevorgang des Stapels wird Push/Push/Push genannt, und die eingefügten Daten befinden sich oben auf dem Stapel
Pop: Der Löschvorgang des Stapels wird als Poppen bezeichnet, und die Popup-Daten befinden sich ebenfalls oben auf dem Stapel.
Implementierung der Push-Operation push--->store Elemente von der Oberseite des Stapels
Sequenztabelle: Es kann als Tail-Insert-Operation betrachtet werden
Verknüpfte Liste: (zirkuläre verknüpfte Liste mit zwei Richtungsköpfen) Der Kopf der Liste wird als die Oberseite des Stapels betrachtet, was die Kopfeinfügung darstellt, und das Ende der Liste wird als die Oberseite des Stapels betrachtet, was die ist Schwanzeinführung
Pop-Operation Pop ---> Elemente von der Oberseite des Stapels entfernen
Sequenztabelle: Das Ende der Tabelle wird als oberster Punkt des Stapels und als Endlöschvorgang betrachtet.
Verknüpfte Liste: (zirkuläre verknüpfte Liste mit zwei Richtungsköpfen) Der Kopf der Liste wird als oberster Punkt des Stapels betrachtet, was die Kopflöschung darstellt, und der hintere Teil der Liste wird als oberster Punkt des Stapels betrachtet, d. h Schwanzlöschung.
#enthalten<stdio.h>
#enthalten<stdlib.h>
Typdefinition int STDataType;
//Sequenztabelle implementiert einen Stapel
Typdefinitionsstruktur Stapel{
STDatentyp* _Daten;
int _Größe;
int _Kapazität;
}Stapel;
void stackInit(stack*st){
wenn (st == NULL)
zurückkehren;
st->_data = NULL;
st->_Größe = st->_Kapazität = 0;
}
void checkCapcacity(stack*st){
wenn (st->_size == st->_capacity){
int neueKapazität = st->_capacity == 0? 1: 2 * st->_capacity;
st->_data = (STDataType*)realloc(st->_data, Größe von (STDataType)* neue Kapazität);
st->_capacity = neueKapazität;
}
}
//Zum Stapeln drücken
void stackPush(stack*st, STDataType val){
wenn (st == NULL)
zurückkehren;
Prüfkapazität(st);
//Schwanzeinfügung
st->_data[st->_size++] = Wert;
}
//Pop
void stackPop(stack*st){
wenn (st == NULL)
zurückkehren;
wenn (st->_size > 0)
st->_Größe--;
}
STDataType stackTop(stack*st){
gibt st->_data[st->_size - 1] zurück;
}
int Stapelgröße(Stapel*st){
wenn (st == NULL)
gebe 0 zurück;
gibt st->_size zurück;
}
ungültiger Test () {
Stapel M;
StapelInit(&st);
stapelPush(&st, 1);
stapelPush(&st, 2);
stapelPush(&st, 3);
stapelPush(&st, 4);
für (int i = 0; i < 4; ++i){
printg("%d", stackTop(&st));
StapelPop(&st);
}
printf("n");
}
int main(){
prüfen();
system("pause");
gebe 0 zurück;
}