2.2 单链表的具体内容
首先,单链表作为线性表的一种实现方式,拥有特质——一对一,用结构体和指针的方式去实现,通过指针移动的方式可以遍历整个链表。相较于顺序表,链表可以更有效的利用空间,也可以防止数据域中的元素泄露。但是如果其中的某一个的指针丢失,会导致后续的数据丢失(顺序表就不需要考虑这些意外)
2.2.1 单链表的代码及具体操作
2.2.1.1 单链表的建立及初始化
typedef struct LinkNode{
char data;
struct LinkNode *next;
} LNode, *LinkList, *NodePtr;
LinkList initLinkList(){
NodePtr tempHeader = (NodePtr)malloc(sizeof(LNode));
tempHeader->data = '\0';
tempHeader->next = NULL;
return tempHeader;
}// Of initLinkList
2.2.1.2 单链表的打印操作
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
2.2.1.3 单链表的添加操作
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
// Step 3. Now add
p->next = q;
}// Of appendElement
2.2.1.4 单链表的节点插入操作
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
2.2.1.5 单链表的删除操作
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
2.2.1.6 单链表的查找操作(此处返回的是查找节点的地址)
NodePtr findElement(LinkList templist, char Find ){
NodePtr p = NULL,q = NULL;
p = templist;
while ((p->next != NULL) && (p->next->data != Find) ){
p = p->next;
}
if(p->next == NULL){
printf("This list don't have this element\r\n");
return NULL;
}
q = p;
return q;
}// Of findElement
2.2.3程序的测试和运行
此处先展示二段测试代码
1.appendInsertDeleteTest(用于测试增 插 删)
void appendInsertDeleteTest(){
// Step 1. Initialize 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);
insertElement(tempList,' ',0);
insertElement(tempList,'u',0);
insertElement(tempList,'o',0);
insertElement(tempList,'y',0);
printList(tempList);
}// Of appendInsertDeleteTest
运行结果
2.findElementTest
void findElementTest(){
//Step 1 struct a list
LinkList tempList = initLinkList();
printList(tempList);
char findE = 0 ;
LinkList FindPtr = 0;
//Step 2 add some elemwent
appendElement(tempList, 'H');
appendElement(tempList, 'e');
appendElement(tempList, 'l');
appendElement(tempList, 'l');
appendElement(tempList, 'o');
appendElement(tempList, '!');
printList(tempList);
//Step 3 putinto the element,return the address
printf("Please tpye in the char \r\n ");
scanf("%c",&findE);
FindPtr=findElement(tempList , findE);
//Step 4 check the result
printf("%p",FindPtr);
}
运行结果
2.2.4收获及总结
1.在闵老师的地址打印测试程序中,我发现链表节点的指针(ListNode)和 data域的指针(LinkList->data)的地址是相同的,而指针域的地址(LinkList->next)相差了8个byte。这意味着前两者是储存在一起的。(不会是联合类型吧?虽然我不懂)
2.对链表的学习,让我更加意识到组织数据储存方式的重要性,不同的储存方式,不仅在计算机的内存中有区别,同时也有对应的实际意义,比如链表不易造成数据泄露,从本质上认识数据的储存方式,能增长有用的逻辑思维。
3.我现在能或多或少地模仿闵老师的代码写法了,虽然到不了那么简洁,但也是初具雏形。在仔细地观察过闵老师的代码后,很多现阶段的逻辑思维也是我模仿不出来的。