C 单链表-删除/添加位置x处的项目
这是一个单链接列表。我有以下代码。我现在想扩展这些代码,以便可以在某个特定位置添加/删除元素。我不知道如何着手实施它 这就是我迄今为止所做的:C 单链表-删除/添加位置x处的项目,c,list,singly-linked-list,C,List,Singly Linked List,这是一个单链接列表。我有以下代码。我现在想扩展这些代码,以便可以在某个特定位置添加/删除元素。我不知道如何着手实施它 这就是我迄今为止所做的: #include <stdio.h> #include <conio.h> #include <stdlib.h> struct list { int amount; struct element *first; }; struct element { int number; str
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
struct list
{
int amount;
struct element *first;
};
struct element
{
int number;
struct element *next;
int *temp;
};
int main()
{
struct list lk;
struct element *ptr, *temp;
int amount;
int i;
printf("How much elements u want enter?");
scanf("%d", &amount);
ptr = (struct element *) calloc(1, sizeof(struct element));
lk.first = ptr;
lk.amount = 0;
printf("Please enter 1. number :");
scanf("%d", &(ptr->number));
temp = ptr;
for (i = 2; i <= amount; i++)
{
printf("Please enter %d. number", i);
ptr = (struct element *) calloc(1, sizeof(struct element));
lk.amount++;
scanf("%d", &(ptr->number));
ptr->next = NULL;
temp->next = ptr;
temp = ptr;
}
ptr = lk.first;
while (ptr != NULL)
{
printf("%d \n", ptr->number);
ptr = ptr->next;
}
getch();
return 0;
}
我在用户输入后测试了这个:
struct list lk;
struct element *ptr, *temp, number1, number2;
int amount;
int i;
printf("Which element u want add:");
scanf("%d", number1.number);
printf("On which position u want add the element?:");
scanf("%d", number2.number);
initList(&lk);
insertInList(&lk, &zahl2, &zahl1);
我在第>
scanf行(“%d”,number1.number)之后得到一个AccessViolentException代码>在列表中插入元素的功能还可以,但我有一些建议:
- 不要将变量命名为与关键字相同的名称(例如new)。这会让其他人很困惑,我不确定是否所有的编译器都会允许这个
- 在普通C语言中,您需要编写例如
struct list*L
而不是list*L
(或者添加一个typedef,例如typedef struct list;
,它允许您编写list*L而不是struct list*L
)
- 在使用指针之前,请始终确保它们不为NULL
- 将返回值添加到函数中,以便调用方能够区分成功和失败
我编写了以下函数:
void initList(struct list* L)
{
if (L)
{
L->amount = 0;
L->first = NULL;
}
}
int insertInList(struct list* L, struct element* position, struct element* newElem)
{
int result = 0;
struct element *iterator;
if (L)
{
/* Check if newElem is already within list and if so don't add it again! */
for (iterator = L->first; iterator != NULL; iterator = iterator->next)
{
if (iterator == newElem)
{
break;
}
}
if (iterator != newElem) /* newElem not within list, yet? */
{
if (position != 0)
{
newElem->next = position->next;
position->next = newElem;
}
else
{
newElem->next = L->first;
L->first= newElem;
}
L->amount++;
result = 1;
}
}
return (result);
}
int deleteFromList(struct list* L, struct element* elem)
{
int result = 0;
struct element *iterator;
if ((L) && (L->amount > 0)) /* list with elements in it? */
{
if (L->first != elem) /* elem is not the first element? */
{
/* iterator all items to find entry preceeding elem */
for (iterator = L->first; iterator != NULL; iterator = iterator->next)
{
if (iterator->next == elem)
{
iterator->next = elem->next; /* set next element to elemen after elem */
result = 1;
break;
}
}
}
else
{
L->first = elem->next; /* set new head of list */
result = 1;
}
if (result == 1) /* item deleted? */
{
L->amount--;
elem->next = NULL; /* ensure next pointer of elem does not point into list! */
}
}
return (result);
}
int deleteIndexFromList(struct list* L, int iElement) /* iElement is zero based: 0=first element, 1=second element, ... */
{
int result = 0;
struct element *iterator;
if ((L) && (L->amount >= iElement))
{
/* iterator all items to find entry preceeding elem */
for (iterator = L->first; iterator != NULL; iterator = iterator->next)
{
if (iElement == 0)
{
result = deleteFromList(L, iterator);
break;
}
iElement--;
}
}
return (result);
}
您可以使用调试器和以下测试程序测试代码:
int main(void)
{
struct list L;
struct element A, B, C, D;
A.number = 5;
B.number = 10;
C.number = 15;
D.number = 20;
initList(&L);
insertInList(&L, NULL, &A);
insertInList(&L, &A, &B);
insertInList(&L, &B, &C);
insertInList(&L, &C, &D);
/* now your list is 5 -> 10 -> 15 -> 20 */
deleteFromList(&L, &A);
/* now your list is 10 -> 15 -> 20 */
deleteFromList(&L, &C);
/* now your list is 10 -> 20 */
return (0);
}
要在“条目N”之后添加条目,只需搜索“条目N”。然后你要做new\u entry->next=current\u entry->next;当前\u条目->下一步=新的\u条目代码>
若要在“条目N”之前添加条目,若要删除“条目N”,则需要在搜索时跟踪上一条条目的地址;因此,当您找到“条目N”时,您仍然知道上一条条目的地址
在这种情况下,删除“条目N”大部分变成previous\u entry->next=current\u entry->next代码>;并在“条目N”变为new\u entry->next=previous\u entry->next之前插入一个新条目;上一个\u条目->下一个=新的\u条目代码>。但是,对于这两种情况,对于“N==0”,前面的条目可能不存在。在这种情况下,您必须修改列表的标题而不是条目
例如(删除,其中something
是结构类型的名称):
注意:完全可以更早地处理n==0
情况(在while
循环之前)。我这样写是为了便于修改搜索条件,并将其转换为删除满足其他条件的第一个条目的内容。让我们从两个特殊情况开始,分别介绍单链接非循环列表。第一种是添加数据的通用方法,它只是继续将节点添加到列表的末尾。其中的函数可能类似于:
/* insert node at end of list */
void insert_end (list *l, int n)
{
struct lnode *ptr = NULL;
if (!(ptr = calloc (1, sizeof *ptr))) {
fprintf (stderr, "%s() error: memory exhausted.\n", __func__);
exit (EXIT_FAILURE);
}
ptr->number = n;
ptr->next = NULL;
if (l->cnt == 0)
{
l->first = ptr;
l->cnt++;
return;
}
lnode *iter = l->first; /* pointer to iterate list */
while (iter->next) iter = iter->next;
iter->next = ptr;
l->cnt++;
}
在上面,您只需为下一个元素分配存储(我将它们保留为节点)。您只需检查金额(重命名为cnt
)是否为0
。如果是,则添加为第一个节点。如果不是,则创建一个指向列表的指针,用作迭代器,并在列表指针上迭代,直到节点->下一个为空
,并在末尾添加新节点
(注意:如果插入效率是关键,使用双链接循环列表,不需要迭代,只需在列表->prev
位置添加一个节点,这样即使在有数亿个节点的列表中,添加速度也会盲目加快)
下一个变体是希望在列表的开头或开头添加一个新节点。在这里,您只需先做ptr->next=l->first
,然后再做l->first=ptr
:
/* insert node at beginning of list */
void insert_start (list *l, int n)
{
struct lnode *ptr = NULL;
if (!(ptr = calloc (1, sizeof *ptr))) {
fprintf (stderr, "%s() error: memory exhausted.\n", __func__);
exit (EXIT_FAILURE);
}
ptr->number = n;
if (l->cnt == 0)
ptr->next = NULL;
else
ptr->next = l->first;
l->first = ptr;
l->cnt++;
}
在列表中的给定位置插入节点怎么样。您需要验证位置(0 cnt
等于lk->cnt
)。您已经看到了如何使用列表指针遍历节点,直到到达最后一个节点为止。进入第n个节点也不例外。要在给定位置插入,您将获得该位置,因此只需迭代pos
次数即可到达插入点:
/* insert node at position */
void insert_pos (list *l, int n, int pos)
{
/* validate position */
if (pos < 0 || pos > l->cnt) {
fprintf (stderr, "%s() error: invalid position.\n", __func__);
return;
}
/* if empty or pos 0, insert_start */
if (l->cnt == 0 || pos == 0) {
insert_start (l, n);
return;
}
struct lnode *ptr = NULL;
if (!(ptr = calloc (1, sizeof *ptr))) {
fprintf (stderr, "%s() error: memory exhausted.\n", __func__);
exit (EXIT_FAILURE);
}
ptr->number = n;
ptr->next = NULL;
lnode *iter = l->first; /* pointer to iterate list */
while (--pos)
iter = iter->next;
if (iter->next)
ptr->next = iter->next;
iter->next = ptr;
l->cnt++;
}
只要我们正在扩展您的列表,您就应该保持main
函数的干净,其中包含print
列表的函数,并且free
完成后分配给列表的所有内存。可以实现这一点的两个辅助函数可以是:
void prn_list (list l)
{
lnode *ptr = l.first;
int i = 0;
while (ptr)
{
printf(" node[%2d] : %d\n", i++, ptr->number);
ptr = ptr->next;
}
}
void free_list (list l)
{
lnode *ptr = l.first;
while (ptr)
{
lnode *del = ptr;
ptr = ptr->next;
free (del);
del = NULL;
}
}
删除作品的方式类似。把所有这些放在一起,你会得到一个带有输入特性的半健壮列表。请注意,struct
还创建了typedef
,以减少键入并提高可读性
#include <stdio.h>
#include <stdlib.h>
// #include <conio.h>
typedef struct lnode
{
int number;
struct lnode *next;
} lnode;
typedef struct
{
int cnt;
lnode *first;
} list;
void insert_end (list *l, int n);
void insert_start (list *l, int n);
void insert_ordered (list *l, int n);
void insert_pos (list *l, int n, int pos);
void prn_list (list l);
void free_list (list l);
int main (void)
{
list lk = { 0, NULL };
int num = 0;
int i = 0;
printf ("\n number of nodes to enter: ");
scanf ("%d", &num);
for (i = 0; i < num; i++)
{
int n = 0;
printf (" enter node[%d]->number: ", i);
scanf("%d", &n);
insert_end (&lk, n);
}
printf ("\n The list contains '%d' nodes.\n", lk.cnt);
printf ("\n The list nodes are:\n\n");
prn_list (lk);
printf ("\n enter number to add at start: ");
scanf("%d", &num);
insert_start (&lk, num);
printf ("\n The list contains '%d' nodes.\n", lk.cnt);
printf ("\n The list nodes are:\n\n");
prn_list (lk);
printf ("\n enter number to add in order: ");
scanf("%d", &num);
insert_ordered (&lk, num);
printf ("\n The list contains '%d' nodes.\n", lk.cnt);
printf ("\n The list nodes are:\n\n");
prn_list (lk);
printf ("\n enter number to add at position: ");
scanf("%d", &num);
printf ("\n position must be (0 <= pos <= %d)\n", lk.cnt);
printf ("\n enter position in list for '%d': ", num);
scanf("%d", &i);
insert_pos (&lk, num, i);
printf ("\n The list contains '%d' nodes.\n", lk.cnt);
printf ("\n The list nodes are:\n\n");
prn_list (lk);
printf ("\n Freeing list memory:\n\n");
free_list (lk);
//getch();
return 0;
}
/* insert node at end of list */
void insert_end (list *l, int n)
{
struct lnode *ptr = NULL;
if (!(ptr = calloc (1, sizeof *ptr))) {
fprintf (stderr, "%s() error: memory exhausted.\n", __func__);
exit (EXIT_FAILURE);
}
ptr->number = n;
ptr->next = NULL;
if (l->cnt == 0)
{
l->first = ptr;
l->cnt++;
return;
}
lnode *iter = l->first; /* pointer to iterate list */
while (iter->next) iter = iter->next;
iter->next = ptr;
l->cnt++;
}
/* insert node at beginning of list */
void insert_start (list *l, int n)
{
struct lnode *ptr = NULL;
if (!(ptr = calloc (1, sizeof *ptr))) {
fprintf (stderr, "%s() error: memory exhausted.\n", __func__);
exit (EXIT_FAILURE);
}
ptr->number = n;
if (l->cnt == 0)
ptr->next = NULL;
else
ptr->next = l->first;
l->first = ptr;
l->cnt++;
}
/* insert node at end of list */
void insert_ordered (list *l, int n)
{
/* if first node of n < first->number */
if (l->cnt == 0 || n < l->first->number) {
insert_start (l, n);
return;
}
struct lnode *ptr = NULL;
if (!(ptr = calloc (1, sizeof *ptr))) {
fprintf (stderr, "%s() error: memory exhausted.\n", __func__);
exit (EXIT_FAILURE);
}
ptr->number = n;
ptr->next = NULL;
lnode *iter = l->first; /* pointer to iterate list */
while (iter->next && n > iter->next->number)
iter = iter->next;
if (iter->next)
ptr->next = iter->next;
iter->next = ptr;
l->cnt++;
}
/* insert node at position */
void insert_pos (list *l, int n, int pos)
{
/* validate position */
if (pos < 0 || pos > l->cnt) {
fprintf (stderr, "%s() error: invalid position.\n", __func__);
return;
}
/* if pos 0, insert_start */
if (l->cnt == 0 || pos == 0) {
insert_start (l, n);
return;
}
struct lnode *ptr = NULL;
if (!(ptr = calloc (1, sizeof *ptr))) {
fprintf (stderr, "%s() error: memory exhausted.\n", __func__);
exit (EXIT_FAILURE);
}
ptr->number = n;
ptr->next = NULL;
lnode *iter = l->first; /* pointer to iterate list */
while (--pos)
iter = iter->next;
if (iter->next)
ptr->next = iter->next;
iter->next = ptr;
l->cnt++;
}
/* print all nodes in list */
void prn_list (list l)
{
lnode *ptr = l.first;
int i = 0;
while (ptr)
{
printf(" node[%2d] : %d\n", i++, ptr->number);
ptr = ptr->next;
}
}
/* free memory for all nodes */
void free_list (list l)
{
lnode *ptr = l.first;
while (ptr)
{
lnode *del = ptr;
ptr = ptr->next;
free (del);
del = NULL;
}
}
#包括
#包括
//#包括
类型定义结构节点
{
整数;
结构lnode*next;
}节点;
类型定义结构
{
int-cnt;
lnode*第一;
}名单;
无效插入结束(列表*l,整数n);
无效插入开始(列表*l,整数n);
无效插入顺序(列表*l,整数n);
无效插入位置(列表*l,整数n,整数位置);
无效prn_列表(列表l);
无作废清单(清单l);
内部主(空)
{
列表lk={0,NULL};
int num=0;
int i=0;
printf(“\n要输入的节点数:”);
scanf(“%d”和&num);
对于(i=0;i编号:”,i);
scanf(“%d”和“&n”);
插入_端(&lk,n);
}
printf(“\n该列表包含“%d”个节点。\n”,lk.cnt);
printf(“\n列表节点为:\n\n”);
prn_列表(lk);
printf(“\n在开始处输入要添加的编号:”);
scanf(“%d”和&num);
插入\u开始(&lk,num);
printf(“\n该列表包含“%d”个节点。\n”,lk.cnt);
printf(“\n列表节点为:\n\n”);
prn_列表(lk);
printf(“\n输入要按顺序添加的编号:”);
scanf(“%d”和&num);
插入已订购的\u(&lk,num);
printf(“\n该列表包含“%d”个节点。\n”,lk.cnt);
printf(“\n列表节点为:\n\n”);
prn_列表(lk);
printf(“\n在以下位置输入要添加的编号:
/* insert node at end of list */
void insert_ordered (list *l, int n)
{
/* if first node of n < first->number */
if (l->cnt == 0 || n < l->first->number) {
insert_start (l, n);
return;
}
struct lnode *ptr = NULL;
if (!(ptr = calloc (1, sizeof *ptr))) {
fprintf (stderr, "%s() error: memory exhausted.\n", __func__);
exit (EXIT_FAILURE);
}
ptr->number = n;
ptr->next = NULL;
lnode *iter = l->first; /* pointer to iterate list */
while (iter->next && n > iter->next->number) {
iter = iter->next;
}
if (iter->next)
ptr->next = iter->next;
iter->next = ptr;
l->cnt++;
}
void prn_list (list l)
{
lnode *ptr = l.first;
int i = 0;
while (ptr)
{
printf(" node[%2d] : %d\n", i++, ptr->number);
ptr = ptr->next;
}
}
void free_list (list l)
{
lnode *ptr = l.first;
while (ptr)
{
lnode *del = ptr;
ptr = ptr->next;
free (del);
del = NULL;
}
}
#include <stdio.h>
#include <stdlib.h>
// #include <conio.h>
typedef struct lnode
{
int number;
struct lnode *next;
} lnode;
typedef struct
{
int cnt;
lnode *first;
} list;
void insert_end (list *l, int n);
void insert_start (list *l, int n);
void insert_ordered (list *l, int n);
void insert_pos (list *l, int n, int pos);
void prn_list (list l);
void free_list (list l);
int main (void)
{
list lk = { 0, NULL };
int num = 0;
int i = 0;
printf ("\n number of nodes to enter: ");
scanf ("%d", &num);
for (i = 0; i < num; i++)
{
int n = 0;
printf (" enter node[%d]->number: ", i);
scanf("%d", &n);
insert_end (&lk, n);
}
printf ("\n The list contains '%d' nodes.\n", lk.cnt);
printf ("\n The list nodes are:\n\n");
prn_list (lk);
printf ("\n enter number to add at start: ");
scanf("%d", &num);
insert_start (&lk, num);
printf ("\n The list contains '%d' nodes.\n", lk.cnt);
printf ("\n The list nodes are:\n\n");
prn_list (lk);
printf ("\n enter number to add in order: ");
scanf("%d", &num);
insert_ordered (&lk, num);
printf ("\n The list contains '%d' nodes.\n", lk.cnt);
printf ("\n The list nodes are:\n\n");
prn_list (lk);
printf ("\n enter number to add at position: ");
scanf("%d", &num);
printf ("\n position must be (0 <= pos <= %d)\n", lk.cnt);
printf ("\n enter position in list for '%d': ", num);
scanf("%d", &i);
insert_pos (&lk, num, i);
printf ("\n The list contains '%d' nodes.\n", lk.cnt);
printf ("\n The list nodes are:\n\n");
prn_list (lk);
printf ("\n Freeing list memory:\n\n");
free_list (lk);
//getch();
return 0;
}
/* insert node at end of list */
void insert_end (list *l, int n)
{
struct lnode *ptr = NULL;
if (!(ptr = calloc (1, sizeof *ptr))) {
fprintf (stderr, "%s() error: memory exhausted.\n", __func__);
exit (EXIT_FAILURE);
}
ptr->number = n;
ptr->next = NULL;
if (l->cnt == 0)
{
l->first = ptr;
l->cnt++;
return;
}
lnode *iter = l->first; /* pointer to iterate list */
while (iter->next) iter = iter->next;
iter->next = ptr;
l->cnt++;
}
/* insert node at beginning of list */
void insert_start (list *l, int n)
{
struct lnode *ptr = NULL;
if (!(ptr = calloc (1, sizeof *ptr))) {
fprintf (stderr, "%s() error: memory exhausted.\n", __func__);
exit (EXIT_FAILURE);
}
ptr->number = n;
if (l->cnt == 0)
ptr->next = NULL;
else
ptr->next = l->first;
l->first = ptr;
l->cnt++;
}
/* insert node at end of list */
void insert_ordered (list *l, int n)
{
/* if first node of n < first->number */
if (l->cnt == 0 || n < l->first->number) {
insert_start (l, n);
return;
}
struct lnode *ptr = NULL;
if (!(ptr = calloc (1, sizeof *ptr))) {
fprintf (stderr, "%s() error: memory exhausted.\n", __func__);
exit (EXIT_FAILURE);
}
ptr->number = n;
ptr->next = NULL;
lnode *iter = l->first; /* pointer to iterate list */
while (iter->next && n > iter->next->number)
iter = iter->next;
if (iter->next)
ptr->next = iter->next;
iter->next = ptr;
l->cnt++;
}
/* insert node at position */
void insert_pos (list *l, int n, int pos)
{
/* validate position */
if (pos < 0 || pos > l->cnt) {
fprintf (stderr, "%s() error: invalid position.\n", __func__);
return;
}
/* if pos 0, insert_start */
if (l->cnt == 0 || pos == 0) {
insert_start (l, n);
return;
}
struct lnode *ptr = NULL;
if (!(ptr = calloc (1, sizeof *ptr))) {
fprintf (stderr, "%s() error: memory exhausted.\n", __func__);
exit (EXIT_FAILURE);
}
ptr->number = n;
ptr->next = NULL;
lnode *iter = l->first; /* pointer to iterate list */
while (--pos)
iter = iter->next;
if (iter->next)
ptr->next = iter->next;
iter->next = ptr;
l->cnt++;
}
/* print all nodes in list */
void prn_list (list l)
{
lnode *ptr = l.first;
int i = 0;
while (ptr)
{
printf(" node[%2d] : %d\n", i++, ptr->number);
ptr = ptr->next;
}
}
/* free memory for all nodes */
void free_list (list l)
{
lnode *ptr = l.first;
while (ptr)
{
lnode *del = ptr;
ptr = ptr->next;
free (del);
del = NULL;
}
}
$ ./bin/ll_single_ins
number of nodes to enter: 3
enter node[0]->number: 5
enter node[1]->number: 7
enter node[2]->number: 9
The list contains '3' nodes.
The list nodes are:
node[ 0] : 5
node[ 1] : 7
node[ 2] : 9
enter number to add at start: 2
The list contains '4' nodes.
The list nodes are:
node[ 0] : 2
node[ 1] : 5
node[ 2] : 7
node[ 3] : 9
enter number to add in order: 6
The list contains '5' nodes.
The list nodes are:
node[ 0] : 2
node[ 1] : 5
node[ 2] : 6
node[ 3] : 7
node[ 4] : 9
enter number to add at position: 4
position must be (0 <= pos <= 5)
enter position in list for '4': 4
The list contains '6' nodes.
The list nodes are:
node[ 0] : 2
node[ 1] : 5
node[ 2] : 6
node[ 3] : 7
node[ 4] : 4
node[ 5] : 9
Freeing list memory:
$ valgrind ./bin/ll_single_ins
==22898== Memcheck, a memory error detector
==22898== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==22898== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==22898== Command: ./bin/ll_single_ins
==22898==
number of nodes to enter: 3
enter node[0]->number: 5
enter node[1]->number: 7
enter node[2]->number: 9
The list contains '3' nodes.
<snip>
==22519== HEAP SUMMARY:
==22519== in use at exit: 0 bytes in 0 blocks
==22519== total heap usage: 5 allocs, 5 frees, 80 bytes allocated
==22519==
==22519== All heap blocks were freed -- no leaks are possible
==22519==
==22519== For counts of detected and suppressed errors, rerun with: -v
==22519== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)