- 单向链表
- 定义
- 创建
- 建链
- 建表-头插法
- 建表-尾插法
- 遍历
- 递归
- 非递归
- 求表长
- 取第i个元素
- 按值查找
- 查p结点前驱
- 查值为e的结点后继
- 插入元素
- 删除元素
- 合并单链表
- 循环链表
- 双向链表
- 定义
- 插入
- 删除
数据结构
单向链表 定义
typedef struct node { int data; struct node *next; }LNode, *linkList; LNode *h,*p; //或者 linkList h,p;
头节点:第一个节点的前设节点,可有可无,也就是俗称的表头
头指针:指向(记录)链式存储中第1个节点位置(地址)的指针变量。
int InitList (linkList &L)//带头节点 { L=new LNode ; if (L==NULL) {printf(“无内存空间可分配”);retutn 0;} L->next=NULL; return 1; }建表-头插法
void ListCreat1(linkList &L) { //用头插法建立带头结点的单链表 LNode *p; L = new LNode; L->next = NULL; //初始化一个空链表,L为头指针 scanf(“% d”, &x); //x是和链表元素具有相同类型的变量,假设为整型 while (x != flag) //flag为结束输入的标志,可自己设置如999 { p = new LNode; //生成新结点 p->data = x; //输入元素值 p->next = L->next; L->next = p; //插入到表头 scanf(“% d”, &x); //读入下一个元素的值 } }建表-尾插法
linkList ListCreat2(linkList &L) { //用尾插法建立带头结点的单链表 LNode *r, *p; L = new LNode; L->next = NULL; r = L; scanf(“% d”, &x); while (x != flag) //设置结束标志 { p = new LNode; p->data = x; //赋值元素值 r->next = p; //在尾部插入新结点 r = p; //r 指向新的尾结点 scanf(“% d”, &x); } r->next = NULL; //最后结点的指针域放空指针 }遍历 递归
void print(linkList L) //非递归 { linkList p = L->next; while (p) { printf(“% d”, p->data); p = p->next; } }非递归
void out(linkList p) //递归 { if (p) { printf(“% c”, p->data); out(p->next); } }求表长
int ListLength(linkList L) {//求带头结点的单链表的长度 LNode *p; int j; p=L->next; //p指向第一结点 j=0; while(p!=NULL) { j++; p=p->next; } //移动p指向下一结点 return j; }取第i个元素
linkList ListGet(linkList L, int i) { //在单链表L中查找第i个元素结点,返回该结点的地址,否则返回空 LNode *p; int j; if (i < 1) { printf(“参数错误”); return NULL; } p = L->next; j = 1; while (p != NULL && j < i) { p = p->next; j++; } if (j == i) return p; else return NULL; }按值查找
linkList ListLocate1(linkList L, int x) { //在单链表L中查找值为x的结点,找到后返回其指针,否则返回空 LNode *p; p = L->next; while (p != NULL && p->data != x) p = p->next; if (!p) { printf(“无值为X的结点”); return NULL; } else return p; }查p结点前驱
linkList ListLocate2(linkList L, LNode *p) { //在单链表L中求p指向的结点(假定存在)的前驱 LNode *pre; if (L->next == p) { printf(“p指向第一元素结点,无前驱”); return NULL; } pre = L->next; while (pre != NULL && pre->next != p) pre = pre->next; if (pre) return pre; else return NULL; }查值为e的结点后继
linkList ListLocate3(linkList L, int e) { //在单链表L中求元素值为e的结点(假定存在)的后继 LNode *p; p = L->next; while (p != NULL && p->data != e) p = p->next; if (p == NULL) { printf(“不存在值为e的结点”); return NULL; } else if (p->next == NULL) { printf(“值为e的结点是最后一个结点,无后继”); return NULL; } else return p->next; }插入元素
void ListInsert(linkList L, LNode *p, int x) {//在结点p之前插入元素为x的结点 LNode *pre; pre = L; while (pre->next != NULL && pre->next != p) pre = pre->next; //找p的直接前驱 if (!pre->next) { printf(“不存在 * p结点”) ;return; } s = new Lnode; //创建新结点 s->data = x; //设置新结点的元素值 s->next = pre->next; pre->next = s; //插入新结点 }删除元素
void ListDel(linkList L, int i) { //删除单链表L上的第i个结点 LNode *pre, *p; if (i < 1) { printf(“参数错误”); return; } if (i == 1) { p = L->next; L->next = p->next; free(p); return; } pre = L->next; j = 1; while (pre != NULL && j < i - 1) { pre = pre->next; j++; } if (pre == NULL) { printf(“删除位置不正确”); return; } p = pre->next; pre->next = p->next; //从链表中删除 delete p; //释放被删除结点 }合并单链表
linkList Union(linkList la, linkList lb) { //将非递减有序的单链表la和lb合并成新的非递减有序单链表lc,并要求利用原表空间 linkList pa, pb, lc, pc; pa = la->next; //pa是链表la的工作指针 pb = lb->next; //pb是链表lb的工作指针 lc = la; //利用原a的表头做c的头 pc = lc; //pc是链表lc的工作指针 while (pa && pb) //la和lb均非空 { if (pa->data <= pb->data) { pc->next = pa; pc = pa; pa = pa->next; } else { pc->next = pb; pc = pb; pb = pb->next; } //lb中元素插入lc } if (pa) pc->next = pa; //若pa未到尾,将pc指向pa else pc->next = pb; //若pb未到尾,将pc指向pb }循环链表
链表尾结点的指针域指向头结点
双向链表如果希望查找前驱的时间复杂度达到O(1),我们可以用空间换时间,每个结点再加一个指向前驱的指针域,使链表可以进行双方向查找。用这种结点结构组成的链表称为双向链表
typedef int ElemType; typedef struct DLNode {ElemType data; struct DLNode *prior,*next; }DLNode,*DlinkList;插入 删除
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)