1. 基础操作
/**
* 遍历输出单链表
*/
void print(LinkList H) {
LinkList p = H->next;
while (p) {
printf("%c", p->data);
p = p->next;
}
}
/**
* 初始化链表
*/
void initList(LinkList *H) {
/* 产生头结点,并使L指向此头结点 */
*H = (LinkList)malloc(sizeof (List));
(* H)->next = NULL;
}
/**
* 初始条件:顺序线性表L已存在。
* 操作结果:若L为空表,则返回TRUE,否则返回FALSE
*/
int listEmpty(LinkList L) {
if(L->next) {
return ERROR;
} else {
return OK;
}
}
/**
* 初始条件:顺序线性表L已存在。
* 操作结果:将L重置为空表
*/
int clearList(LinkList *L) {
LinkList p,q;
p = (*L)->next; /* p指向第一个结点 */
while(p) { /* 没到表尾 */
q = p->next;
free(p);
p = q;
}
(*L)->next = NULL; /* 头结点指针域为空 */
return OK;
}
/**
* 初始条件:顺序线性表L已存在。
* 操作结果:返回L中数据元素个数
*/
int listLength(LinkList L) {
int i = 0;
LinkList p = L->next; /* p指向第一个结点 */
while(p) {
i++;
p = p->next;
}
return i;
}
2、以头插法建立单链表
/**
* 以头插法建立单链表
* 以"#"符为结束符
*/
void createFromHead(LinkList H) {
List *node;
ElementType type;
int flag = 1;
while (flag) {
type = getchar();
if ('#' != type) {
node = (List *)malloc(sizeof(List));
node->data = type;
node->next = H->next;
H->next = node;
} else {
flag = 0;
}
}
}
3、以尾插法建立单链表
/**
* 以尾插法建立单链表
* 以"#"符为结束符
*/
void createFromEnd(LinkList H) {
List *node;
ElementType type;
int flag = 1;
while(flag) {
type = getchar();
if ('#' != type ) {
node = (List *)malloc(sizeof(List));
node->data = type;
H->next = node;
H = node;
} else {
flag = 0;
H->next = NULL;
}
}
}
4、在单链表L中查找第i个结点
/**
* 在单链表L中查找第i个结点
*/
List *get(LinkList L, int i) {
List *list = L->next;
int index = 1;
while (index != i && list->next != NULL) {
index++;
list = list->next;
}
return list;
}
5、在单链表L中查找值等于key的个结点
/**
* 在单链表L中查找值等于key的个结点
*/
List *locate(LinkList L, ElementType key) {
List *list = L->next;
while (list->data != key && list->next != NULL) {
list = list->next;
}
return list;
}
6、在单链表的第i位插入元素e
/**
* 在单链表的第i位插入元素e
*/
int insertList(LinkList L, int i, ElementType e) {
List *list = L, *p;
int index = 0;
while (index < i - 1 && list->next != NULL) {
index++;
list = list->next;
}
/**
* 跳出循环是因为list在链表最后或i<1,所以一定是插入位置不合法
*/
if (index != i -1) {
printf("插入位置不合法!");
return ERROR;
}
p = (List *)malloc(sizeof(List));
p->data = e;
p->next = list->next;
list->next = p;
return OK;
}
7、删除单链表的第i位元素
/**
* 删除单链表的第i位元素,并将删除的元素保存至元素e中
*/
int deleteList(LinkList L, int i, ElementType *e) {
List *list = L, *p;
int index = 0;
while (index < i - 1 && list->next != NULL) {
index++;
list = list->next;
}
/**
* 跳出循环是因为list在链表最后或i<1,所以一定是位置不合法
*/
if (index != i -1) {
printf("位置不合法!");
return ERROR;
}
p = list->next;
*e = p->data;
list->next = p->next;
/*一定要记得释放删除的结点所占内存空间*/
free(p);
return OK;
}
8、完整实例
#include <stdio.h>
#include <stdlib.h>
#define OK 1
#define ERROR 0
typedef char ElementType;
typedef struct Node {
ElementType data;
struct Node * next;
} List, *LinkList;
void print(LinkList H);
void initList(LinkList *H);
int listEmpty(LinkList L);
int clearList(LinkList *L);
int listLength(LinkList L);
void createFromHead(LinkList H);
void createFromEnd(LinkList H);
List *get(LinkList L, int i);
List *locate(LinkList L, ElementType key);
int insertList(LinkList L, int i, ElementType e);
int deleteList(LinkList L, int i, ElementType *e);
int main(int argc, char *argv[]) {
LinkList H;
initList(&H);
printf("头插法实现链表:\n");
createFromHead(H);
printf("头插法结果:\n");
print(H);
List *result = get(H, 3);
printf("\n查找第3位元素,结果:%c\n", result->data);
printf("\n尾插法实现链表:\n");
createFromEnd(H);
printf("尾插法结果:\n");
print(H);
printf("\n往链表的第3位插入元素F:\n");
char element = 'F';
insertList(H, 3, element);
printf("插入结果:\n");
print(H);
char e;
deleteList(H, 4, &e);
printf("\n删除链表的第4位元素:%c\n", e);
print(H);
int i = clearList(&H);
printf("\n遍历清空后的链表:\n");
print(H);
printf("链表的长度length(H) = %d\n", listLength(H));
return 0;
}
/**
* 遍历输出单链表
*/
void print(LinkList H) {
LinkList p = H->next;
while (p) {
printf("%c", p->data);
p = p->next;
}
}
/**
* 初始化链表
*/
void initList(LinkList *H) {
/* 产生头结点,并使L指向此头结点 */
*H = (LinkList)malloc(sizeof (List));
(* H)->next = NULL;
}
/**
* 初始条件:顺序线性表L已存在。
* 操作结果:若L为空表,则返回TRUE,否则返回FALSE
*/
int listEmpty(LinkList L) {
if(L->next) {
return ERROR;
} else {
return OK;
}
}
/**
* 初始条件:顺序线性表L已存在。
* 操作结果:将L重置为空表
*/
int clearList(LinkList *L) {
LinkList p,q;
p = (*L)->next; /* p指向第一个结点 */
while(p) { /* 没到表尾 */
q = p->next;
free(p);
p = q;
}
(*L)->next = NULL; /* 头结点指针域为空 */
return OK;
}
/**
* 初始条件:顺序线性表L已存在。
* 操作结果:返回L中数据元素个数
*/
int listLength(LinkList L) {
int i = 0;
LinkList p = L->next; /* p指向第一个结点 */
while(p) {
i++;
p = p->next;
}
return i;
}
/**
* 以头插法建立单链表
* 以"#"符为结束符
*/
void createFromHead(LinkList H) {
List *node;
ElementType type;
int flag = 1;
while (flag) {
type = getchar();
if ('#' != type) {
node = (List *)malloc(sizeof(List));
node->data = type;
node->next = H->next;
H->next = node;
} else {
flag = 0;
}
}
}
/**
* 以尾插法建立单链表
* 以"#"符为结束符
*/
void createFromEnd(LinkList H) {
List *node;
ElementType type;
int flag = 1;
while(flag) {
type = getchar();
if ('#' != type ) {
node = (List *)malloc(sizeof(List));
node->data = type;
H->next = node;
H = node;
} else {
flag = 0;
H->next = NULL;
}
}
}
/**
* 在单链表L中查找第i个结点
*/
List *get(LinkList L, int i) {
List *list = L->next;
int index = 1;
while (index != i && list->next != NULL) {
index++;
list = list->next;
}
return list;
}
/**
* 在单链表L中查找值等于key的个结点
*/
List *locate(LinkList L, ElementType key) {
List *list = L->next;
while (list->data != key && list->next != NULL) {
list = list->next;
}
return list;
}
/**
* 在单链表的第i位插入元素e
*/
int insertList(LinkList L, int i, ElementType e) {
List *list = L, *p;
int index = 0;
while (index < i - 1 && list->next != NULL) {
index++;
list = list->next;
}
/**
* 跳出循环是因为list在链表最后或i<1,所以一定是插入位置不合法
*/
if (index != i -1) {
printf("插入位置不合法!");
return ERROR;
}
p = (List *)malloc(sizeof(List));
p->data = e;
p->next = list->next;
list->next = p;
return OK;
}
/**
* 删除单链表的第i位元素,并将删除的元素保存至元素e中
*/
int deleteList(LinkList L, int i, ElementType *e) {
List *list = L, *p;
int index = 0;
while (index < i - 1 && list->next != NULL) {
index++;
list = list->next;
}
/**
* 跳出循环是因为list在链表最后或i<1,所以一定是位置不合法
*/
if (index != i -1) {
printf("位置不合法!");
return ERROR;
}
p = list->next;
*e = p->data;
list->next = p->next;
/*一定要记得释放删除的结点所占内存空间*/
free(p);
return OK;
}
9、总结
- 一定要理清结点之间的关系
- 删除结点后要注意释放内存空间
- 插入结点或new 结点后,需要申请内存空间