当链表的每个结点只包含一个指针域时,我们称此链表为单链表。
关于单链表的存取,有时候我们在单链表的第一个结点(有效元素)之前附设一个结点,称之为头结点;指向头结点的指针,称之为头指针;对单链表的存取必须从头指针开始进行,由于单链表的最后一个数据元素没有直接后继,则指针为NULL。
对于头结点,数据域可以不存储任何信息,也可存储如链表长度等附加信息。
下面是带头结点的单链表与空表的比较图。
头指针与头结点不同,头结点即第一个结点,头指针是指向第一个结点的指针。链表中可以没有头结点,但不能没有头指针。
关于头指针:
- 在线性表的链式存储结构中,头指针是指链表指向第一个结点的指针,若链表有头结点,则头指针就是指向链表头结点的指针。
- 头指针具有标识作用,故常用头指针冠以链表的名字。
- 无论链表是否为空,头指针均不为空。头指针是链表的必要元素。
关于头结点:
- 头结点是为了操作的统一与方便而设立的,放在第一个元素结点之前,其数据域一般无意义(当然有些情况下也可存放链表的长度、用做监视哨等等)。
- 有了头结点后,对在第一个元素结点前插入结点和删除第一个结点,其操作与对其它结点的操作统一了。
- 首元结点也就是第一个元素的结点,它是头结点后边的第一个结点。
- 头结点不是链表所必需的。
头插法建立单链表:
尾插法建立单链表:
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include "iostream" using namespace std; #define ListSize 10 //单链表的创建 typedef struct LNode { int data;//数据域 struct LNode *next;//链接域 }LNode,*Linklist; //单链表的初始化 bool InitList(Linklist &L) { L = new LNode;//创建一个新的结点作为头结点,用头指针L指向头结点 L->next = NULL;//让头结点的指针域为空 return true; } //判断单链表是否为空表:指针域那边为空 bool ListEmpty(Linklist L) { if (L->next) return false; else return true; } //销毁单链表---不保留头结点 bool DestroyList(Linklist &L) { LNode *p; while (L) { p = L; L = L->next; delete p; } return true; } //清空单链表---保留头指针和头结点,头结点的指针域要置为空 bool DeleteList(Linklist &L) { LNode *p, *q; p = L->next; while (p) { q = p->next; delete p; p = q; } L->next = NULL; return true; } //求单链表的表长 int ListLength(Linklist L) { int i = 0; LNode *p; p = L->next; while (p) { p = p->next; i++; } return i; } //取第i个元素的值 bool GetElem(Linklist L, int i, int &e) { LNode *p; p = L->next; int j = 1; while (p && j<i) { p = p->next; j++; } //查找到最后的情况以及i可能为负数的情况 if (!p || j > i) return false; e = p->data; return true; } //单链表的查找---查找某个元素值,返回该元素的地址 LNode *LocateElem(Linklist L, int e) { LNode *p; p = L->next; while (p && p->data != e) { p = p->next; } return p; } //单链表的查找---查找某个元素值,返回该元素的序号 int LocateElemInt(Linklist L, int e) { LNode *p; p = L->next; int i = 1; while (p && p->data != e) { p = p->next; i = i + 1; } if (p) return i; else return 0; } //单链表的插入---在第i个结点前插入值为e的结点(需要找第i-1个结点) bool ListInsert(Linklist &L, int i, int e) { LNode *p, *s; p = L; int j = 0; while (p && j < i - 1) { p = p->next; } if (!p || j > i-1) return false; s = new LNode; s->data = e; s->next = p->next; p->next = s; return true; } //单链表的删除---删除第i个结点,需要找到第i-1个结点 bool DeleteList(Linklist &L, int i, int &e) { LNode *p, *q; int j = 0; p = L; while (p && j < i - 1) { p = p->next; } if (!(p->next) || j > (i-1)) return false; q = p->next; e = q->data; p->next = p->next->next; delete q; return true; } //头插法建立单链表 void CreatList_H(Linklist &L, int n) { L = new LNode; L->next = NULL; for (int i = n; i > 0; i--) { LNode *p = new LNode;//建立新结点 cin >> p->data;//读入数据 p->next = L->next; L->next = p; } cout << "创建长度为" << n << "的单链表完毕!"<<endl; } //尾插法建立单链表 void CreatList_R(Linklist &L, int n) { L = new LNode; L->next = NULL; LNode *r = L; for (int i = 0; i < n; i++) { LNode *p = new LNode; cin >> p->data; p->next = NULL; r->next = p; r = p; } } //单链表内容的遍历 void ListDisply(Linklist L) { printf("单链表中的内容为:"); LNode *p; p = L->next; while (p) { printf("%d ", p->data); p = p->next; } printf("\n\n\n\n"); } int main() { //创建一个链表 Linklist L; InitList(L); Linklist K; InitList(K); Linklist P; InitList(P); //创建三个结点 LNode *a, *b, *c; a = new LNode; b = new LNode; c = new LNode; //判断空表 if (!ListEmpty(L)) printf("it is not empty!\n"); else printf("it is empty!\n"); //将三个结点串成串连成线儿 L->next = a; a->next = b; b->next = c; c->next = NULL; if (!ListEmpty(L)) printf("it is not empty!\n"); else printf("it is empty!\n"); //给三个结点的数据域赋值 a->data = 23; b->data = 87; c->data = 99; printf("the length of list is: %d\n", ListLength(L)); //获取第i个元素的值 int e; GetElem(L, 2, e); printf("the value of second is:%d\n", e); //单链表的查找---返回地址 printf("\n\nLocateElem--23: %x\n", (unsigned)LocateElem(L, 23)); printf("LocateElem--87: %x\n", (unsigned)LocateElem(L, 87)); printf("LocateElem--99: %x\n", (unsigned)LocateElem(L, 99)); //单链表的查找---返回序号 printf("LocateElemInt--87: %d\n\n\n", LocateElemInt(L, 23)); //头插法建立单链表---输入几个元素 cout << "头插法建立单链表,请输入数据:" << endl; CreatList_H(K, 5); printf("the length of list is: %d\n", ListLength(K)); //单链表的遍历 ListDisply(K); //尾插法建立单链表---输入几个元素 cout << "尾插法建立单链表,请输入数据:" << endl; CreatList_R(P,5); printf("the length of list is: %d\n\n", ListLength(P)); //单链表的遍历 ListDisply(P); getchar(); getchar(); getchar(); return 0; }