由于顺序表的插入删除操作需要移动大量的元素,影响了运行效率,因此引入了线性表的链式存储——单链表。单链表通过一组任意的存储单元来存储线性表中的数据元素,不需要使用地址连续的存储单元,因此它不要求在逻辑上相邻的两个元素在物理位置上也相邻。
代码如下(编译器:Dev):
#include <stdio.h>
#include <malloc.h>
/**
*Linked list of characters. The key is data.
*/
typedef struct LinkNode{
char data;
struct LinkNode *next;
}LNode, *LinkList, *NodePtr;
/**
*Initialize the list with a header.\
*@return The pointer to the header.
*/
LinkList initLinkList(){
NodePtr tempHeader = (NodePtr)malloc(sizeof(LNode));
tempHeader->data = '\0';
tempHeader->next = NULL;
return tempHeader;
}// of initLinkList
/*
*Print the list.
*@param paraHeader The header of the list.
*/
void printList(NodePtr paraHeader){
NodePtr p = paraHeader->next;
while (p != NULL){
printf("%c",p->data);
p = p->next;
}// of while
printf("\r\n");
}// of printLIst
/**
*Add an element to the tail.
*@@param paraHeader The header of the list.
* @param paraChar The given char.
*/
void appendElement(NodePtr paraHeader, char paraChar){
NodePtr p,q;
//Step 1.Construct a new node.
q = (NodePtr)malloc(sizeof(LNode));
q->data = paraChar;
q->next = NULL;
//step 2. Search to the tail.
p = paraHeader;
while(p->next != NULL){
p = p->next;
}// of while
//sStep 3. NOw and/link.
p->next = q;
}// of appendElement
/**
*Insert an ekement to the given position.
*@param paraHeader The haedar of the list.
*@param parachar the given char.
*@param paraPosition The given position.
*/
void insertElement (NodePtr paraHeader, char paraChar, int paraPosition){
NodePtr p,q;
// step 1. Search to the position.
p = paraHeader;
for (int i = 0; i < paraPosition; i ++){
p = p->next;
if (p == NULL){
printf("the position %d is beyond the scope of the list.", paraPosition);
return;
}// of if
}// of for i
//step 2. Construct a new node.
q = (NodePtr)malloc(sizeof(LNode));
q->data = paraChar;
//step 3. Now link
printf("linking\r\n");
q->next = p->next;
p->next = q;
} // of insertElement
/**
*Delete an element from the list.
*@param paraHeader The header of the list.
*@param paraChar The given char.
*/
void deleteElement(NodePtr paraHeader, char paraChar){
NodePtr p,q;
p = paraHeader;
while ((p->next != NULL) && (p->next->data != paraChar)){
p = p->next;
}//of while
if (p->next == NULL){
printf("cannot delete %c\r\n", paraChar);
return;
}// of if
q = p->next;
p->next = p->next->next;
free(q);
}// of deleteElement
/**
* Unit test.
*/
void appendInsertDeleteTest(){
// step 1. Initialze an empty list.
LinkList tempList = initLinkList();
printList(tempList);
//step 2. Add some characters.
appendElement(tempList,'H');
appendElement(tempList,'e');
appendElement(tempList,'l');
appendElement(tempList,'l');
appendElement(tempList,'o');
appendElement(tempList,'!');
printList(tempList);
//step 3. Delete some characters (the first occurrence).
deleteElement(tempList,'e');
deleteElement(tempList,'a');
deleteElement(tempList,'o');
printList(tempList);
//step 4. Insert to a given position.
insertElement(tempList,'o',1);
printList(tempList);
}// of appendInsertDeleteTest
/**
*Address test: beyond the book.
*/
void basicAddressTest(){
LNode tempNodel, tempNode2;
tempNodel.data = 4;
tempNodel.next = NULL;
tempNode2.data = 6;
tempNode2.data = NULL;
printf("The first node: %d, %d, %d\r\n",&tempNodel, &tempNodel.data, &tempNodel.next);
printf("The second node: %d, %d, %d\r\n",&tempNode2, &tempNode2.data, &tempNode2.next);
tempNodel.next = &tempNode2;
}// Of basicAddressTest
/**
* The entrance.
*/
int main(){
appendInsertDeleteTest();
}// Of main
运行结果
体会总结
1、单链表的查找
单链表的查找与顺序表相差无几,从链表的第一个节点开始依次将节点与查找对象进行比较,若查找成功则返回节点的地址值,若失败则返回NULL。
2、单链表的插入
单链表的插入首先需要进行一次查找
如上图所示,查找中找到节点A。原来节点A中的指针域指向B,为了实现插入节点C,只需将A的指针域指向C后,C的指针域指向B即可实现逻辑关系的变化。
3、单链表的删除
如果我们想要在单链表中删除节点q,则只需要将q的前继结点p的指针绕过q直接指向q的后继节点即可,如下图所示:
代码操作为查找节点p,p.next=q.next,释放节点q的空间即可。