单链表是一种链式存取的数据结构,,链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。以“结点的序列”表示的线性表称作线性链表(单链表),单链表是链式存取的结构。
先看老师代码
#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;
//Stpe 1.Construct a new node.
q = (NodePtr)malloc(sizeof(LNode));
q->data = paraChar;
q->next = NULL;
//Stpe 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
/**
* Insert an element to the given position.
* @param paraHeader The header 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. 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);
}// Of appendInsertDeleteTest
/**
* Address test: beyond the book.
*/
void basicAddressTest() {
LNode tempNode1, tempNode2;
tempNode1.data = 4;
tempNode1.next = NULL;
tempNode2.data = 6;
tempNode2.next = NULL;
printf("The first node: %d, %d, %d\r\n",
&tempNode1, &tempNode1.data, &tempNode1.next);
printf("The second node: %d, %d, %d\r\n",
&tempNode2, &tempNode2.data, &tempNode2.next);
tempNode1.next = &tempNode2;
}// Of basicAddressTest
/**
* The entrance.
*/
int main() {
appendInsertDeleteTest();
}// Of main
运行结果
Hello!
Cannot delete a
Hll!
linking
Holl!
Press any key to continue
自己实现单链表的插入
void deletement(NodePtr L, int i, ElemType e)
{
int j;
NOdePtr p, q;
p = L;
j = 1;
whlie(p->next && j < i)
{
p = p->next;
j++;
}
if (!(p->next) || j > i)
{
return ERROR;
}
q = p->next;
p->next = q->next;
*e = q->data;
free(q);
return OK;
}
自己实现单链表的删除
假设元素a2的结点为q,要实现结点q删除单链表的操作,其实就是将他的钱继结点的指针绕过指向向后继结点即可。
即p->next=p->next->next;
或者 q=p->next; p->next=q->next;
void deleteElement(NodePtr L, int i, ElemType e)
{
int j;
NOdePtr p, q;
p = L;
j = 1;
whlie(p->next && j < i)
{
p = p->next;
j++;
}
if (!(p->next) || j > i)
{
return ERROR;
}
q = p->next;
p->next = q->next;
*e = q->data;
free(q);
return OK;
}
总结
从第i个位置开始,插入连续10个元素,对于顺序存储结构意味着,每一次插入都需要移动n-i个位置,所以每次都是0(n)。
而单链表,我们只需要在第一次时,找到第i个位置的指针,此时为0(n),接下来只是简单地通过赋值移动指针而已,时间复杂度都是0(1)。
显然,对于插入或删除数据越频繁的操作,单链表的效率优势就越是明显