C-Sprache --- Datenstrukturexperiment --- Zusammenführen von Sequenztabellen --- Grundoperation der verknüpften Liste --- Fokus auf die Analyse von Josephs Problem

vorne geschrieben

Es gibt viele Möglichkeiten, das Experiment zu schreiben, aber in diesem Artikel wird #define nicht zum Definieren der Kapazität verwendet, was sehr alt und veraltet ist. Alle experimentellen Themen werden dynamisch entwickelt. Wenn Sie in Zukunft C++ zum Schreiben verwenden, verwenden Sie möglicherweise mehr Syntax ...

In diesem Artikel werden zwei Experimente mit Datenstrukturen vorgestellt

Dabei liegt der Schwerpunkt auf der Analyse des Joseph-Problems

Der Benennungsstil des Codes im Experiment ähnelt dem Stil des folgenden Blogs, und der gesamte Prozess ist ein von Hand zerrissenes Diagramm

Die folgenden Artikel stellen die Sequenztabelle und die verknüpfte Liste vor und sind nicht klar

Hand-Tear-Sequenztabelle.
Hand-Tear-Einzelverknüpfte Liste

Nachdem Sie die Sequenztabelle und die einfach verknüpfte Liste beherrscht haben, ist das Experiment die oben erwähnte einfache Anwendung

Konsolidierung von Sequenzlisten

Definieren Sie die sequentielle Speicherstruktur der linearen Tabelle und verwenden Sie die definierte Struktur, um die Zusammenführung zweier linearer Tabellen zu realisieren. (Erstellen Sie zwei geordnete Sequenztabellen und führen Sie die beiden geordneten Sequenztabellen zu einer geordneten Sequenztabelle zusammen.)
Anforderungen an den Inhalt:
Erstellen Sie eine geordnete Tabelle: 12, 23, 46, 67
, 85. Erstellen Sie eine geordnete Tabelle: 5, 59, 94.
Führen Sie die beiden geordneten Tabellen zu einer geordneten Tabelle zusammen, um die Richtigkeit des Codes zu überprüfen.

Code

//建立有序表:12,23,46,67,85
//建立有序表:5,59,94
//两个有序顺序表合并为一个有序顺序表,验证代码的正确性。

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

typedef int SLDataType;
typedef struct SeqList
{
    
    
	SLDataType* a;
	int size;
	int capacity;
}SeqList;

void SListInit(SeqList* ps)
{
    
    
	//assert(ps);
	ps->size = 0;
	ps->capacity = 4;
	ps->a = (SLDataType*)malloc(sizeof(SLDataType) * 4);
	if (ps->a == NULL)
	{
    
    
		perror("malloc fail");
		return;
	}
}

void SListDestroy(SeqList* ps)
{
    
    
	assert(ps);
	ps->a = NULL;
	ps->capacity = 0;
	ps->size = 0;
}

void SListCheckCapacity(SeqList* ps)
{
    
    
	assert(ps);
	if (ps->size == ps->capacity)
	{
    
    
		SLDataType* tmp = NULL;
		tmp = (SLDataType*)realloc(ps->a, sizeof(SLDataType)*(ps->capacity) * 2);
		if (tmp == NULL)
		{
    
    
			perror("realloc fail");
			return;
		}
		ps->a = tmp;
		ps->capacity *= 2;
		//printf("The capacity now:%d\n", ps->capacity);
	}
	else
	{
    
    
		return;
	}
}

void SListPushBack(SeqList* ps, SLDataType x)
{
    
    
	assert(ps);
	SListCheckCapacity(ps);
	ps->a[ps->size] = x;
	ps->size++;
}

void SListPrint(SeqList* ps)
{
    
    
	assert(ps);
	for (int i = 0; i < ps->size; i++)
	{
    
    
		printf("%d ", ps->a[i]);
	}
	printf("\n");
}

void SListMerge(SeqList* ps1, SeqList* ps2)
{
    
    
	assert(ps1);
	assert(ps2);
	SeqList ps;
	SListInit(&ps);
	for (int i = 0; i < ps1->size; i++)
	{
    
    
		SListPushBack(&ps, ps1->a[i]);
	}
	for (int i = 0; i < ps2->size; i++)
	{
    
    
		SListPushBack(&ps, ps2->a[i]);
	}
	printf("The result of merging two seqlists is:\n");
	SListPrint(&ps);
}

int main()
{
    
    
	SeqList ps1;
	SeqList ps2;
	SListInit(&ps1);
	SListInit(&ps2);
	int quantity1 = 0, quantity2 = 0, input = 0;

	printf("Input quantity of seqlist1-> ");
	scanf("%d", &quantity1);
	for (int i = 0; i < quantity1; i++)
	{
    
    
		scanf("%d", &input);
		SListPushBack(&ps1, input);
	}

	printf("Input quantity of seqlist2-> ");
	scanf("%d", &quantity2);
	for (int i = 0; i < quantity2; i++)
	{
    
    
		scanf("%d", &input);
		SListPushBack(&ps2, input);
	}

	SListMerge(&ps1, &ps2);
	return 0;
}

Code herunterladen

Gitee-Download-Link

Grundlegende Funktionsweise einer verknüpften Liste

Definieren Sie die verknüpfte Speicherstruktur der linearen Liste, definieren Sie den Knotentyp und verwenden Sie die definierte Struktur, um grundlegende Vorgänge wie Erstellen, Einfügen, Löschen, Abfragen und Ausgabe der verknüpften Liste zu realisieren.
Adressbuchverwaltung (erforderlicher Inhalt); Joseph Ring (optionaler Inhalt)
Erforderliche Inhaltsanforderungen:
1. Die Knotentypdefinition des Korrespondenten lautet wie folgt:
typedef struct { char num[5] ; // number char name[9] ; / /name char sex[3]; //gender char phone[13]; //phone char addr[31]; //address ]DataType; 2. Die verkettete Speicherstruktur der linearen Tabelle ist wie folgt definiert: typedef struct node { / /Knotentypdefinition DataType data; //Knotendatenfeld struct node * next; //Knotenzeigerfeld } ListNode; typedef ListNode * LinkList; ListNode * p; //Definieren Sie eine Zeigervariable für einen Knoten LinkList head; // Definieren Sie den Kopfzeiger, der auf die einfach verknüpfte Liste zeigt. 3. Anforderungen an die Gestaltung des Hauptsteuermenüs Nach der Ausführung des Programms werden die Inhalte und Eingabeaufforderungen von 6 Menüelementen angezeigt:















  1. Die Einrichtung der mit dem Adressbuch verknüpften Liste
  2. Einfügen des entsprechenden Knotens
  3. Korrespondierende Knotenabfragen
  4. Löschen des entsprechenden Knotens
  5. Die Ausgabe der verknüpften Adressbuchliste
  6. Verlassen Sie das Verwaltungssystem.
    Bitte wählen Sie 0–5.
    Verwenden Sie die Ziffern 0–5, um Menüpunkte auszuwählen, andere Eingaben funktionieren nicht.

Optionale Inhaltsanforderungen:
Eine Beschreibung von Josephs Problem lautet: 30 Passagiere sind auf demselben Boot und es ist aufgrund der starken Überladung sowie des starken Windes und der Wellen äußerst gefährlich. Deshalb sagte der Kapitän den Passagieren, dass der Rest nur überleben könne, wenn die Hälfte der Passagiere ins Meer geworfen werde. Hilflos hatte jeder keine andere Wahl, als dieser Methode zuzustimmen und stimmte zu, dass 30 Personen einen Kreis bildeten, beginnend mit der ersten Person, der Reihe nach zählend, bis zur neunten Person zählend, sie ihn ins Meer warfen und dann von dort aus losfuhren die nächste Person. , Zählen Sie bis zur neunten Person und werfen Sie sie dann ins Meer usw., bis noch 15 Passagiere übrig sind. Fragen Sie, an welchen Orten sie ins Meer geworfen werden?

1. Verwenden Sie die Einweg-Speicherstruktur für zirkuläre verknüpfte Listen, um diesen Prozess zu simulieren, und geben Sie die Nummern jeder Person in der Reihenfolge aus, in der sie aus der Warteschlange entfernt werden.
2. Um die Allgemeingültigkeit nicht zu verlieren, ändern Sie 30 in eine beliebige eingegebene positive Ganzzahl n, und die Obergrenze der Anzahl der Berichte (ursprünglich 9) ist ebenfalls eine optionale positive Ganzzahl k. Auf diese Weise wird der Algorithmus wie folgt beschrieben:
(1) Erstellen Sie eine einzelne kreisförmige verknüpfte Liste mit n Knoten.
(2) Auswahl der Lebenden und Toten:
p zeigt auf den ersten Knoten der verknüpften Liste und das anfängliche i ist auf 1 gesetzt;
while (i<= n/2) // Die Hälfte der Knoten löschen
{ k-1 Schritte entlang der Kette von dem Knoten vorwärts bewegen, auf den p zeigt;
den k-ten Knoten löschen (den Knoten, auf den q zeigt). ); ​​p zeigt auf den nächsten Knoten von q;
Gibt seine Position q->data aus;
i erhöht sich um 1;
}
(3) Gibt die Positionen aller Überlebenden aus.

3. Testergebnisse
Bei einer Gesamtzahl von 30 Personen beträgt die Obergrenze der Anzahl der Meldungen 9, dann
beträgt die Anzahl der Verstorbenen: 9, 18, 27, 6, 16, 26, 7, 19, 30, 12 , 24, 8, 22,
5 , 23 Die Zahlen sind: 1, 2, 3, 4, 10, 11, 13, 14, 15, 17, 20, 21, 25, 28, 29

Code

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

typedef  struct
{
    
    
	char  num[5];    //编号
	char  name[9];   //姓名
	char  sex[3];     //性别
	char  phone[13];  //电话
	char  addr[31];   //地址
}DataType;

typedef struct node
{
    
    
	DataType data;
	struct node* next;
}ListNode;

//头节点用head
//定义一个指向结点的指针变量 ListNode* p;

ListNode* BuyListNode(DataType x);

void ListNodePush(ListNode** phead);

DataType Buynewdata();

void ListNodePrint(ListNode** phead);

int ListNodeFind(ListNode* head, const char* Findname);

void ListNodePop(ListNode** phead, const char* Popname);

ListNode* BuyListNode(DataType x)
{
    
    
	ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
	if (newnode == NULL)
	{
    
    
		perror("malloc fail");
		return NULL;
	}
	newnode->next = NULL;
	newnode->data = x;
	return newnode;
}

DataType Buynewdata()
{
    
    
	DataType newdata;
	printf("请依次输入编号 姓名 性别 电话 地址\n");
	scanf("%s %s %s %s %s",
		newdata.num, newdata.name, newdata.sex, newdata.phone, newdata.addr);
	return  newdata;
}

void ListNodePush(ListNode** phead)
{
    
    
	assert(phead);
	ListNode* newnode = BuyListNode(Buynewdata());
	if (*phead == NULL)
	{
    
    
		*phead = newnode;
	}
	else
	{
    
    
		newnode->next = *phead;
		*phead = newnode;
	}
}

void ListNodePrint(ListNode** phead)
{
    
    
	ListNode* cur = *phead;
	printf("%-5s%-10s%-8s%-13s%-31s\n",
		"编号", "姓名", "性别", "电话", "地址");
	while (cur)
	{
    
    
		printf("%-5s%-10s%-8s%-13s%-31s\n",
			cur->data.num, cur->data.name, cur->data.sex,
			cur->data.phone, cur->data.addr);
		cur = cur->next;
	}
}

int ListNodeFind(ListNode* head, const char* Findname)
{
    
    
	ListNode* cur = head;
	while (cur)
	{
    
    
		if (strcmp(Findname, cur->data.name) == 0)
		{
    
    
			printf("找到了,该人的信息如下\n");
			printf("%-5s%-10s%-8s%-13s%-31s\n",
				"编号", "姓名", "性别", "电话", "地址");
			printf("%-5s%-10s%-8s%-13s%-31s\n",
				cur->data.num, cur->data.name, cur->data.sex,
				cur->data.phone, cur->data.addr);
			return 1;
		}
		else
		{
    
    
			cur = cur->next;
		}
	}
	printf("找不到信息\n");
	return 0;
}

void ListNodePop(ListNode** phead, const char* Popname)
{
    
    
	assert(*phead);
	assert(phead);
	if (ListNodeFind(*phead, Popname))
	{
    
    
		ListNode* Findnode = *phead;
		ListNode* prev = *phead;
		while (strcmp(Findnode->data.name, Popname) != 0)
		{
    
    
			prev = Findnode;
			Findnode = Findnode->next;
		}
		prev->next = Findnode->next;
		free(Findnode);
		Findnode = NULL;
		printf("删除该人信息成功\n");
		return;
	}
	else
	{
    
    
		printf("找不到该人信息\n");
		return;
	}
}

void menu()
{
    
    
	printf("*********************************************\n");
	printf("****1.建立信息表************** 2.插入信息 ****\n");
	printf("****3.查询信息  ************** 4.删除信息 ****\n");
	printf("****5.打印信息  ************** 0.退出     ****\n");
	printf("*********************************************\n");
}

void SetupListNode(ListNode** phead)
{
    
    
	int num = 0;
	printf("建立链表成功,开始录入信息\n");
	printf("输入要录取信息的个数->");
	scanf("%d", &num);
	while (num--)
	{
    
    
		ListNodePush(phead);
	}
}

void FindFunction(ListNode* head)
{
    
    
	char Findname[20] = {
    
     0 };
	printf("输入要查找的人名");
	scanf("%s", Findname);
	ListNodeFind(head, Findname);
}

void PopFunction(ListNode** phead)
{
    
    
	char Popname[20] = {
    
     0 };
	printf("输入要查找的人名");
	scanf("%s", Popname);
	ListNodePop(phead, Popname);
}

int main()
{
    
    
	menu();
	int input = 0;
	ListNode* head = NULL;
	do
	{
    
    
		printf("请选择->");
		scanf("%d", &input);
		switch (input)
		{
    
    
		case 1:
			SetupListNode(&head);
			break;
		case 2:
			if (head == NULL)
			{
    
    
				printf("通讯录还未建立,请先建立\n");
				break;
			}
			else
			{
    
    
				ListNodePush(&head);
				break;
			}
		case 3:
			if (head == NULL)
			{
    
    
				printf("通讯录还未建立,请先建立\n");
				break;
			}
			else
			{
    
    
				FindFunction(head);
				break;
			}
		case 4:
			if (head == NULL)
			{
    
    
				printf("通讯录还未建立,请先建立\n");
				break;
			}
			else
			{
    
    
				PopFunction(&head);
				break;
			}
		case 5:
			if (head == NULL)
			{
    
    
				printf("通讯录还未建立,请先建立\n");
				break;
			}
			else
			{
    
    
				ListNodePrint(&head);
				break;
			}
		case 0:
			break;
		default:
			printf("请重新选择\n");
			break;
		}
		menu();
	} while (input);
	return 0;
}

Code herunterladen

Gitee-Download-Link

Joseph Frage

Problemanalyse

Eine Beschreibung von Josephs Problem lautet: 30 Passagiere nehmen dasselbe Boot, was aufgrund der starken Überladung, des starken Windes und der großen Wellen äußerst gefährlich ist. Deshalb sagte der Kapitän den Passagieren, dass der Rest nur überleben könne, wenn die Hälfte der Passagiere ins Meer geworfen werde. Hilflos hatte jeder keine andere Wahl, als dieser Methode zuzustimmen und stimmte zu, dass 30 Personen einen Kreis bildeten, beginnend mit der ersten Person, der Reihe nach zählend, bis zur neunten Person zählend, sie ihn ins Meer warfen und dann von dort aus losfuhren die nächste Person. , Zählen Sie bis zur neunten Person und werfen Sie sie dann ins Meer usw., bis noch 15 Passagiere übrig sind. Fragen Sie, an welchen Orten sie ins Meer geworfen werden?

  1. Verwenden Sie die Einweg-Speicherstruktur für zirkuläre verknüpfte Listen, um diesen Prozess zu simulieren, und geben Sie die Nummern jeder Person in der Reihenfolge aus, in der sie aus der Warteschlange entfernt werden.
  2. Um die Allgemeingültigkeit nicht zu verlieren, ändern Sie 30 in eine beliebige eingegebene positive Ganzzahl n, und die Obergrenze der Anzahl der Berichte (ursprünglich 9) ist ebenfalls eine optionale positive Ganzzahl k. Der Algorithmus wird somit wie folgt beschrieben:
1) 创建含有n个结点的单循环链表;
2) 生者与死者的选择:

p指向链表第一个结点,初始i 置为1

while (i<=n/2)   //删除一半的结点

{
    
      
从p指向的结点沿链前进k-1步;

删除第k个结点(q所指向的结点);

p指向q的下一个结点;

输出其位置q->data;

i自增1}
3) 输出所有生者的位置。
  1. Testergebnisse
    Für die Gesamtzahl von 30 beträgt die Obergrenze der Anzahl der Berichte 9, dann
    beträgt die Anzahl der Verstorbenen: 9, 18, 27, 6, 16, 26, 7, 19, 30, 12, 24, 8, 22, 5, 23
    Die Zahl der Lebenden Für: 1, 2, 3, 4, 10, 11, 13, 14, 15, 17, 20, 21, 25, 28, 29

Das traditionelle Joseph-Problem kann durch die Verwendung eines kreisförmigen Arrays gelöst werden. In der vorherigen Einführung in den Vektor wurde erwähnt, dass die Verwendung eines kreisförmigen Arrays zur Lösung des Joseph-Problems verwendet wird. Daher erfordert der Titel hier, dass wir eine verknüpfte Liste verwenden, um dieses Problem zu lösen

Der gesamte Prozess ist nun in mehrere Phasen unterteilt: Erstellen Sie zunächst die verknüpfte Liste, fügen Sie dann die Daten in die verknüpfte Liste ein, löschen Sie dann die angeforderten Elemente aus der verknüpften Liste und geben Sie schließlich die verknüpfte Liste aus.

Die folgenden Punkte müssen während des gesamten Prozesses beachtet werden

1. Um das Problem der zirkulären verknüpften Liste zu lösen

Sie können dies durch Zeichnen eines Bildes erkennen. Jedes Mal, wenn Sie den Schwanzknoten auf den Kopf zeigen möchten, müssen Sie nach jedem Einfügen den Schwanzknoten finden und die Richtung des Schwanzknotens ändern.

Fügen Sie hier eine Bildbeschreibung ein
2. Um das Problem zu lösen, wie das zu löschende Element gefunden wird

Erklären Sie zunächst die Idee: Die Idee besteht darin, einen Cur-Zeiger zu definieren, der auf den zu löschenden Knoten zeigt. Es gibt kein Problem mit dieser Idee selbst, aber das Problem besteht darin, dass es ein Problem bei der Implementierung gibt Code

Das erste Problem besteht darin, dass cur cur=cur->next durchlaufen muss, um das zu löschende Element zu finden. Das Problem besteht darin, dass
bei dieser Frage mehrere Schleifen erforderlich sind, um 15 Elemente zu löschen und jedes Mal zu löschen Mal wird es auf 9 gemeldet, sodass Cur tatsächlich nur 8 Mal durchlaufen muss, um zur Position 9 zu gelangen

Das zweite Problem ist die durch das Löschen des Elements verursachte Inkonsistenz. Wenn der Cur-Knoten nach dem Löschen des Elements nicht verarbeitet wird, unterscheidet sich die aktuelle Position des Cur-Elements tatsächlich von der Anfangsposition. Angenommen, die verknüpften Listenelemente sind 1, 2, 3 ... In der Reihenfolge sortieren, dann beginnt cur erneut auf 1 zu zeigen. Nach dem Durchlaufen muss nun Element 9 gelöscht werden. Nach dem Löschen von Element 9 sollte cur tatsächlich erneut vorgerückt werden, damit cur auf den Anfang zeigen kann Position „1“

Der Folgeprozess zur Lösung dieser beiden Probleme ist sehr einfach: Der Code hier verfügt nicht über eine Makrodefinition im Voraus, und nachfolgende Änderungen müssen direkt durch Ändern der Daten vorgenommen werden.

Code

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

typedef int LTDataType;
typedef struct ListNode
{
    
    
	LTDataType data;
	struct ListNode* next;
}ListNode;

void ListNodePush(ListNode** phead,LTDataType x)
{
    
    
	assert(phead);
	ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
	if (newnode == NULL)
	{
    
    
		perror("malloc fail");
		return;
	}
	newnode->data = x;
	newnode->next = NULL;

	if (*phead == NULL)
	{
    
    
		*phead = newnode;
		newnode->next = newnode;
	}
	else
	{
    
    
		ListNode* tail = *phead;
		while (tail->next != *phead)
		{
    
    
			tail = tail->next;
		}
		newnode->next = *phead;
		*phead = newnode;
		tail->next = *phead;
	}
}

void ListNodePop(ListNode** phead,ListNode* cur)
{
    
    
	ListNode* prev = *phead;
	ListNode* next = *phead;
	while (prev->next != cur)
	{
    
    
		prev = prev->next;
	}
	next = cur->next;
	prev->next = next;
	//free(cur);
	//cur = NULL;
}

void ListNodePrint(ListNode* head)
{
    
    
	assert(head);
	ListNode* cur = head->next;
	printf("%d->", head->data);
	while (cur!=head)
	{
    
    
		printf("%d->", cur->data);
		cur = cur->next;
	}
}

int main()
{
    
    
	ListNode* plist = NULL;
	for (int i = 30; i > 0; i--)
	{
    
    
		ListNodePush(&plist, i);
	}
	int a = 15;
	ListNode* cur = plist;
	while (a--)
	{
    
    
		for (int i = 0; i < 8; i++)
		{
    
    
			cur = cur->next;
		}
		ListNodePop(&plist, cur);
		cur = cur->next;
	}
	ListNodePrint(plist);
	return 0;
}

Supongo que te gusta

Origin blog.csdn.net/qq_73899585/article/details/131685764
Recomendado
Clasificación