单链表的定义
为了建立数据之间的线性关系,因此对于每个链表结点,除了存放自身的信息(data)之外,还要保存指向后继结点(next)的指针,因此需要一个指针变量指向下一个结点。
struct Node
{
ElemType data; //数据域
struct Node* next; //指针域
};
struct Node* p=(struct Node*)malloc(sizeof(struct Node));
//增加一个新的结点,在内存中申请一个结点所需的空间,并用p指向这个结点
由于新增结点每次都需要反复打上struct,因此采用typedef关键字,进行数据类型的重命名
使用方法:typedef <数据类型> <别名>
因此上述的新增结点方式可以改成:
typedef struct Node Node
Node *p=(Node *)malloc(sizeof(Node));
下面看个例子:
typedef int *intPointer;
int i = 10;
intPointer p= &i;
//int *p= &i;
printf("i的地址:%d\n", &i);
printf("指针变量p中保存的值:%d\n", p);
printf("i的值:%d\n", i);
printf("指针变量p指向的变量的值:%d\n", *p);
return 0;
由此看出,typedef int *intPointer使得intPointer具有声明指针类型的功能,即int *p <=>intPointer p。
因此在声明结点结构时可以:
typedef struct Node
{
int data;
struct Node* next;
}Node,*LinkList;
此时,LinkList等同于Node *,例如:
Node *L 和 LinkList L是等价的。
Node *L强调这是一个结点
LinkList L强调这是一个链表,这样更便于程序的阅读。
#include<stdio.h>
#include<stdlib.h>
typedef struct Node
{
int data;
struct Node* next;
}Node, *LinkList;
//初始化单链表(带头结点)
_Bool initLinkList(LinkList L)
{
L = (Node*)malloc(sizeof(Node));
if (L == NULL)
return 0; //内存不足,初始化失败
else
{
L->next = NULL; //L就是头结点
return 1;
}
}
//判断链表是否为空
_Bool Empty(LinkList L)
{
return L->next == NULL;
}
//按下标插入(带头结点)
_Bool insertLinkList(LinkList L, int pos, int e)
{
Node* p; //p指向当前扫描到的结点
p = L;
int i;
if (pos < 0)
return 0;
else
{
for (i = 0; i < pos && p != NULL; i++)
{
p = p->next;
}
if (p == NULL)
return 0;
Node *newNode = (Node *)malloc(sizeof(Node));
newNode->data = e;
newNode->next = p->next;
p->next = newNode;
return 1;
}
}
//删除结点,返回删除的结点的值给e
_Bool deleteLinkList(LinkList L, int pos, int *e)
{
if (pos < 0)
return 0;
Node *p = L; //p指向的是0号结点
int i;
for (i = 0; i < pos; i++)
{
p = p->next;
}
Node *q = p->next; //要删除的结点即为q
p->next = q->next;
*e = q->data;
free(q); //释放结点空间
return 1;
}
//按位查找
Node* searchLinkList(LinkList L, int pos)
{
if (pos < 0)
return NULL;
Node *p = L;
int i;
for (i = 0; i <= pos && p!=NULL; i++)
{
p = p->next;
//此时i为几p就指向结点几
}
if (p == NULL)
return NULL;
return p;
}
void printLinkList(LinkList L)
{
Node *p = L;
while (p != NULL)
{
p = p->next;
if (p != NULL)
printf("%d\t", p->data);
}
printf("\n");
}
int LinkMain()
{
//测试typedef
/*typedef int *intPointer;
int i = 10;
intPointer p= &i;
//int *p= &i;
printf("i的地址:%d\n", &i);
printf("指针变量p中保存的值:%d\n", p);
printf("i的值:%d\n", i);
printf("指针变量p指向的变量的值:%d\n", *p);
*/
Node* node = (Node *)malloc(sizeof(Node));
node->data = 10;
node->next = NULL;
LinkList L=node;
initLinkList(L);
for (int i = 0; i < 10; i++)
{
insertLinkList(L, i, i + 1);
}
printf("初始化的链表为:");
printLinkList(L);
if (insertLinkList(L, 13, 100))
{
printf("插入元素成功,插入后的链表为:");
printLinkList(L);
}
else
{
printf("插入元素失败!请检查插入位置是否有误\n");
}
printf("删除0号结点后链表为:");
int item;
deleteLinkList(L, 0, &item);
printLinkList(L);
printf("删除0号结点的值为:%d\n",item);
printf("删除8号结点后链表为:");
int item1;
deleteLinkList(L, 8, &item1);
printLinkList(L);
printf("删除8号结点的值为:%d\n", item1);
//test按位查找
Node *node1=searchLinkList(L, -1);
if (node1 != NULL)
{
printf("node1:%d\n", node1->data);
}
else
{
printf("error position!\n");
}
return 0;
}
运行结果: