C语言单链表
苏州程序大白 人气:0存储结构
typedef int dataType;//爱护据类型 typedef struct Node { DataType data; // 结点数据 struct Node *next; // 指向下一个结点的指针 } Node, *LinkList;
基本功能
- 头插法创建单链表void CreateListHead( LinkList &head)
- 尾插法创建单链表void CreateListTail( LinkList &head)
- 获取指定位置的元素 int GetElement(LinkList head, int i, DataType &e)
- 获取指定元素的位置 int LocateElement(LinkList head, int e)
- 在指定位置插入元素 int InsertList(LinkList head, int i, DataType e)
- 删除指定位置的元素 int DeleteList(LinkList head, int i, DataType &e)
- 获取单链表的长度 int LengthLinkList(LinkList head)
- 合并两个非递减的单链表 void MergeList(LinkList La, LinkList Lb, LinkList &Lc)
- 寂链表void Destroy( LinkList &L)
- 遍历打印单链表中的所有元素 void PrintList(LinkList head)
头插法创建单链表
每次添加链的结点都能找到头结点的第1号位置,所以创建单表中的元素的顺序是输入元素的逆序。
/** * 头插法创建单链表,输入以-1结束 */ void CreateListHead(LinkList &head) { DataType x; LinkList p; head = (LinkList)malloc(LEN); head->next = NULL; scanf("%d", &x); while (x != -1) { p = (LinkList)malloc(LEN); p->data = x; p->next = head->next; // 新增的结点指向头结点的下一个结点 head->next = p; // 头结点指向新增的结点 scanf("%d", &x); } }
尾插法创建单链表
每次新增的结点都放在单链表的后面,接下来和接下来的顺序保持一致。
/** * 尾插法创建单链表,输入以-1结束 */ void CreateListTail(LinkList &head) { LinkList p, q; DataType x; head = (LinkList)malloc(LEN); q = head; scanf("%d", &x); while (x != -1) { p = (LinkList)malloc(LEN); p->data = x; q->next = p; q = p; scanf("%d", &x); } q->next = NULL; }
获取指定位置的元素
/** * 获取指定位置的元素 * @param head 指向单链表头结点的指针(头指针) * @param i 位置 * @param e 用来存放对应位置的元素值 * @return 0:获取失败;1:获取成功 */ int GetElement(LinkList head, int i, DataType &e) { LinkList p = head->next; int j = 1; while (p && j < i) { // 依次后移,直至为空或到达位置 p = p->next; j++; } if (!p || j > i) { // p为空表示位置超过最大位置,j > i表示位置不合法(i < 1) return 0; } e = p->data; return 1; }
在指定位置插入元素
/** * 在单链表插入元素到位置i * @param head 单链表的头指针 * @param i 插入位置 * @param e 插入元素 * @return 1:插入成功,0:插入失败 */ int InsertList(LinkList head, int i, DataType e) { LinkList p = head; // 从头结点开始 int j = 1; while (p && j < i) { // 找到插入位置的前一个结点 p = p->next; j++; } if (!p || j > i) { // p为空或i < 1,插入位置不合法 return 0; } LinkList q = (LinkList)malloc(LEN); // 创建新结点 q->data = e; q->next = p->next; // 将新结点指向前一个结点的后一个结点 p->next = q; // 前一个结点指向新结点 // 执行上述两个操作后,达到的效果是新结点插入到了前一个结点的后面 }
删除指定位置的元素
/** * 删除指定位置的元素 * @param head * @param i 位置 * @param e 被删除的元素的值存放在e中 * @return 1:删除成功,0:删除失败 */ int DeleteList(LinkList head, int i, DataType &e) { LinkList p = head; int j = 1; while (p && j < i) { // 找到位置的前一个结点 p = p->next; j++; } if (!p || j > i) { return 0; } LinkList s = p->next; e = s->data; p->next = s->next; // 改变前一个结点的指向,使其指向删除结点的后一个结点 free(s); return 1; }
获取单链表的长度
/** * 获取单链表的长度 * @param head * @return 单链表的长度 */ int LengthLinkList(LinkList head) { LinkList p = head->next; int count = 0; while (p) { count++; p = p->next; } return count; }
合并两个非递减的单链表
合并两个非递减的单链,新链表仍然保持非递减。
/** * 合并两个非递减的单链表,新的链表仍然非递减 * @param La * @param Lb * @param Lc */ void MergeList(LinkList La, LinkList Lb, LinkList &Lc) { LinkList pa, pb, pc; pa = La->next; pb = Lb->next; pc = Lc = (LinkList)malloc(LEN); while (pa && pb) { if (pa->data <= pb->data) { pc->next = pa; pc = pa; pa = pa->next; } else { pc->next = pb; pc = pb; pb = pb->next; } } pc->next = pa ? pa : pb; free(Lb); }
晴链表
/** * 销毁链表 */ void Destroy(LinkList &L) { LinkList p, q; p = L; while (p) { // 遍历所有结点,释放内存 q = p; p = p->next; free(q); } L = NULL; // L置为NULL }
遍历打印单链表
/** * 遍历打印单链表的所有元素 */ void PrintList(LinkList head) { LinkList p = head->next; if (p == NULL) { cout << "List is NULL!" <<endl; } else { while (p != NULL) { printf("%d ", p->data); p = p->next; } printf("\n"); } }
附上完整代码
#include<cstdlib> using namespace std; #define LEN sizeof(Node) typedef int DataType; typedef struct Node { DataType data; struct Node *next; } Node, *LinkList; /** * 头插法创建单链表 * @param head */ void CreateListHead(LinkList &head) { DataType x; LinkList p; head = (LinkList)malloc(LEN); head->next = NULL; scanf("%d", &x); while (x != -1) { p = (LinkList)malloc(LEN); p->data = x; p->next = head->next; head->next = p; scanf("%d", &x); } } /** * 尾插法创建单链表 * @param head */ void CreateListTail(LinkList &head) { LinkList p, q; DataType x; head = (LinkList)malloc(LEN); q = head; scanf("%d", &x); while (x != -1) { p = (LinkList)malloc(LEN); p->data = x; q->next = p; q = p; scanf("%d", &x); } q->next = NULL; } /** * 获取指定位置的元素 * @param head 单链表头指针 * @param i 位置 * @param e 获取的元素赋值该参数 * @return 0:获取失败;1:获取成功 */ int GetElement(LinkList head, int i, DataType &e) { LinkList p = head->next; int j = 1; while (p && j < i) { p = p->next; j++; } if (!p || j > i) { return 0; } e = p->data; return 1; } /** * 获取某个元素的位置 * @param head * @param e * @return 元素的位置 */ int LocateElement(LinkList head, int e) { LinkList p = head->next; int j = 1; while (p && p->data != e) { p = p->next; j++; } if (!p) { return 0; } return j; } /** * 在单链表插入元素到位置i * @param head 单链表的头指针 * @param i 插入位置 * @param e 插入元素 * @return 1:插入成功,0:插入失败 */ int InsertList(LinkList head, int i, DataType e) { LinkList p = head; int j = 1; while (p && j < i) { p = p->next; j++; } if (!p || j > i) { return 0; } LinkList q = (LinkList)malloc(LEN); q->data = e; q->next = p->next; p->next = q; } /** * 删除指定位置的元素 * @param head * @param i 位置 * @param e 被删除的元素的值存放在e中 * @return 1:删除成功,0:删除失败 */ int DeleteList(LinkList head, int i, DataType &e) { LinkList p = head; int j = 1; while (p && j < i) { p = p->next; j++; } if (!p || j > i) { return 0; } LinkList s = p->next; e = s->data; p->next = s->next; free(s); return 1; } /** * 获取单链表的长度 * @param head * @return */ int LengthLinkList(LinkList head) { LinkList p = head->next; int count = 0; while (p) { count++; p = p->next; } return count; } /** * 合并两个非递减的单链表,新的链表仍然非递减 * @param La * @param Lb * @param Lc */ void MergeList(LinkList La, LinkList Lb, LinkList &Lc) { LinkList pa, pb, pc; pa = La->next; pb = Lb->next; pc = Lc = (LinkList)malloc(LEN); while (pa && pb) { if (pa->data <= pb->data) { pc->next = pa; pc = pa; pa = pa->next; } else { pc->next = pb; pc = pb; pb = pb->next; } } pc->next = pa ? pa : pb; free(Lb); } /** * 销毁链表 * @param L */ void Destroy(LinkList &L) { LinkList p, q; p = L; while (p) { q = p; p = p->next; free(q); } L = NULL; } /** * 遍历打印单链表的所有元素 * @param head */ void PrintList(LinkList head) { LinkList p = head->next; if (p == NULL) { cout << "List is NULL!" <<endl; } else { while (p != NULL) { printf("%d ", p->data); p = p->next; } printf("\n"); } } int main() { LinkList L; printf("头插法创建单链表:(输入以-1结束)\n"); CreateListHead(L); PrintList(L); printf("尾插法创建单链表:(输入以-1结束)\n"); CreateListTail(L); PrintList(L); InsertList(L, 1, 100); printf("在1号位置插入100后,单链表如下:\n"); PrintList(L); DataType e; DeleteList(L, 1, e); printf("删除1号位置的元素,被删除的元素为:\n"); printf("删除后的单链表为:\n"); PrintList(L); printf("单链表的长度为:%d\n", LengthLinkList(L)); GetElement(L, 1, e); printf("1号位置的元素为:%d\n"); printf("元素4在单链表中的位置为:%d\n", LocateElement(L, 4)); cout << endl; LinkList La, Lb, Lc; printf("尾插法创建单链表La:\n"); CreateListTail(La); PrintList(La); printf("尾插法创建单链表Lb:\n"); CreateListTail(Lb); PrintList(Lb); MergeList(La, Lb, Lc); printf("合并单链表La和Lb后的新单链表Lc如下:\n"); PrintList(Lc); return 0; }
运行结果:
注意:
写法采用了C++引用参数的写法,LinkList &head,C语言下不支持这种写法,需要在C++环境下使用,即.cpp文件。
下面附上C语言的:
/** * LinkList 本身已经是结构体指针,参数再使用LinkList *的形式 * 可以理解为要想改变一个结构体指针,则需要取指针的指针。 * 类似于改变int a,则需要使用 int *a,这里要改变LinkList head,则需要使用LinkList *head */ void CreatListTail(LinkList *head) { int x; LinkList *p, *q; *head = (LinkList *) malloc(LEN); q = *head; scanf("%d", &x); while (x != -1) { p = (LinkList *) malloc(LEN); p->data = x; q->next = p; q = p; scanf("%d", &x); } q->next = NULL; } // 可以不传参,函数里面定义头指针,创建链表,然后把头指针返回,主函数用结构体指针接收即可 LinkList CreateListhead() { int x; LinkList *head, *p; head = (LinkList *) malloc(LEN); head->next = NULL; scanf("%d", &x); while (x != -1) { p = (LinkList *) malloc(LEN); p->data = x; p->next = head->next; head->next = p; } return head; }
加载全部内容