C 有头结点链表的若干操作
比无头节点的要简单很多
文章目录
创建
typedef struct Node {
int data;
struct Node * next;
} LNode, * LinkNode;
//创建,丝毫不用理会第一个节点特殊情况
void creatLink(LinkNode * q){
int i;
LinkNode e, p1;
//头节点
*q = (LinkNode)malloc(sizeof(LNode));
(*q)->next = NULL;
p1 = *q;
for (i = 0; i < 10; i++) {
//创建新节点
e = (LinkNode)malloc(sizeof(LNode));
e->data = i+1;
e->next = NULL;
//把新节点接在链表中
p1->next = e;
p1 = e;
}
}
输出
//输出,让过第一个头节点
void putout(LinkNode q){
LinkNode p1 = q->next;
while (p1) {
printf("%d ", p1->data);
p1 = p1->next;
}
printf("\n");
}
访问第i个元素
/*访问第i个元素,并且返回,以参数的方式返回了,这个就是C语言的局限了,
只能返回一个参数,不像别的能返回个元组什么的*/
Status findElement(LinkNode q, int i, int *e){
if(i < 1) return ERR;
LinkNode p1 = q->next;
//很实在从1开始
int n = 1;
while (p1) {
//这个就是第几个了
if(n == i) {
*e = p1->data;
return OK;
}
p1 = p1->next;
n++;
}
return ERR;
}
在i个位置前插入
Status insertElement(LinkNode q, int i, int e){
if(i < 1 || !q) return ERR;
//前驱p2,后继p1
LinkNode p1 = q->next, p2 = q;
int n = 1;
while (p1) {
//还是先找到第i个位置,以及在第i个位置上的元素和其前驱元素
if(n == i){
LinkNode element = (LinkNode)malloc(sizeof(LNode));
element->data = e;
element->next = NULL;
//插入元素
p2->next = element;
element->next = p1;
return OK;
}
n++;
p2 = p1;
p1 = p1->next;
}
return ERR;
}
删除第i个元素
//删除第i个元素
Status deleteElement(LinkNode *q, int i, int *e){
if(i < 1 || !((*q)->next)) return ERR;
//还是前驱后继
LinkNode p1 = (*q)->next, p2 = (*q);
int n = 1;
while (p1) {
//找到第i个元素
if(n == i)
{
(*e) = p1->data;
p2->next = p1->next;
free(p1);
return OK;
}
n++;
p2 = p1;
p1 = p1->next;
}
return ERR;
}
头插
//头插
Status inserthead(LinkNode *q, int e) {
if(!(*q)) return ERR;
LinkNode p1 = *q;
//从头开始
LinkNode element = (LinkNode)malloc(sizeof(LNode));
element->data = e;
element->next = p1->next;
p1->next = element;
return OK;
}
逆置
//逆置
void reverse(LinkNode *q){
//将头节点独立出来,惯例找前驱后继
LinkNode p1, p2;
p1 = (*q)->next;
(*q)->next = NULL;
//将元素一次取出来,再按着头插法,插进去
while (p1) {
p2 = p1;
p1 = p1->next;
//每次取出来的元素都插在最前面
p2->next = (*q)->next;
(*q)->next = p2;
}
}
尾插
//尾插
Status inserttail(LinkNode *q, int e) {
if(!(*q)) return ERR;
LinkNode p1 = *q;
//p1就是最后一个节点
while (p1->next) {
p1 = p1->next;
}
LinkNode element = (LinkNode)malloc(sizeof(LNode));
element->data = e;
element->next = NULL;
//接上
p1->next = element;
return OK;
}
排序
//排序
void sort(LinkNode *q){
LinkNode p1, p2;
int temp;
p1 = p2 = (*q)->next;
//选择
// for (; p1->next; p1 = p1->next) {
// for (p2 = p1->next; p2; p2 = p2->next) {
// if(p1->data > p2->data){
// temp = p2->data;
// p2->data = p1->data;
// p1->data = temp;
// }
// }
// }
//冒泡 每趟只能遍历到最后,有些许浪费
for (; p1->next; p1 = p1->next) {
for (p2 = (*q)->next; p2->next; p2 = p2->next) {
if(p2->data > p2->next->data){
temp = p2->data;
p2->data = p2->next->data;
p2->next->data = temp;
}
}
}
}
两个有序链表合并在一起,合并在一起的链表也要有序
//la和lb递增,归并起来lc
LinkNode combine2Links(LinkNode *q1, LinkNode *q2){
//LinkNode =(* LNode)就是一个指针
//把两个链表的第一个有数字的结点取出来,
LinkNode p1 = (*q1)->next;
LinkNode p2 = (*q2)->next;
//我现在认为链表1就是合并成新的链表
LinkNode L = *q1;
//第二个链表的头结点于我来说莫得用了
free(*q2);
//遍历p1和p2,哪个小先放哪个
while (p1 && p2) {
if(p2->data > p1->data){
L->next = p1;
p1 = p1->next;
}else{
L->next = p2;
p2 = p2->next;
}
L = L->next;
}
//最后剩下哪个全接上去
if(p2){
L->next = p2;
}
if(p1){
L->next = p1;
}
//返回链表1
return *(q1);
}
找出链表中数据最大的节点并返回
LinkNode findmax(LinkNode q){
LinkNode p1 = q->next, max = NULL;
//记录值
int m = 0;
while (p1) {
//只要发现比它大的,记录节点也刷新值
if(m < p1->data){
m = p1->data;
max = p1;
}
//往后走
p1 = p1->next;
}
return max;
}
链表中最小的节点放在最前面
//将链表最小节点移动到链表最前面
void insertMinNode(LinkNode *head){
//遍历的时候前驱后继
LinkNode p1 = (*head)->next;
LinkNode p = (*head);
//最小点的前驱后继
LinkNode minPreNode = NULL, minNode = NULL;
//初值
int min = p1->data;
//动起来
while (p1) {
//只要发现还有小的就更新节点
if(min > p1->data){
min = p1->data;
minNode = p1;
minPreNode = p;
}
//驱动着往后走
p = p1;
p1 = p1->next;
}
//遍历完一次,留下的就是我们要的了,ps.链表中最好不要出现两个一样小的
//删除原有的位置
minPreNode->next = minNode->next;
//添加到新的地方
minNode->next = (*head)->next;
(*head)->next = minNode;
}
有序链表中去除相同值的节点
//有序链表中去除相同值的节点
void deleteSimilarNode(LinkNode *head){
//前驱后继
LinkNode prenode = (*head)->next;
LinkNode node = prenode->next;
//往下走
while (node) {
//要是相等就走后面的,前头等着直到走完
if(prenode->data == node->data){
prenode->next = node->next;
free(node);
node = prenode->next;
}
else
//既然不相等,就都往后移动
{
prenode = node;
node = node->next;
}
}
}
升序表里比x小的有几个
//升序表里比x小的有几个
int lessThanNode(LinkNode q, int x){
LinkNode p1 = q->next;
int n = 0;
while (p1) {
//升序,碰见比x大的,那后面肯定都是大的,跳出
if(p1->data >= x)
break;
n++;
p1 = p1->next;
}
return n;
}
//
// main.c
// 单链表有头结点
//
// Created by 赫凯 on 2018/10/23.
// Copyright © 2018年 赫凯. All rights reserved.
//
#include <stdio.h>
#include <stdlib.h>
#define OK 1
#define ERR 0
#define num 0
typedef int Status;
typedef struct Node {
int data;
struct Node * next;
} LNode, * LinkNode;
//创建,丝毫不用理会第一个节点特殊情况
void creatLink(LinkNode * q){
int i;
LinkNode e, p1;
*q = (LinkNode)malloc(sizeof(LNode));
(*q)->next = NULL;
p1 = *q;
for (i = 0; i < num; i++) {
e = (LinkNode)malloc(sizeof(LNode));
e->data = i+1;
e->next = NULL;
p1->next = e;
p1 = e;
}
}
//输出,让过第一个头节点
void putout(LinkNode q){
LinkNode p1 = q->next;
while (p1) {
printf("%d ", p1->data);
p1 = p1->next;
}
printf("\n");
}
//访问第i个元素
Status findElement(LinkNode q, int i, int *e){
if(i < 1) return ERR;
LinkNode p1 = q->next;
int n = 1;
while (p1) {
if(n == i) {
*e = p1->data;
return OK;
}
p1 = p1->next;
n++;
}
return ERR;
}
//在i个位置前插入
Status insertElement(LinkNode q, int i, int e){
if(i < 1 || !q) return ERR;
LinkNode p1 = q->next, p2 = q;
int n = 1;
while (p1) {
if(n == i){
LinkNode element = (LinkNode)malloc(sizeof(LNode));
element->data = e;
element->next = NULL;
p2->next = element;
element->next = p1;
return OK;
}
n++;
p2 = p1;
p1 = p1->next;
}
return ERR;
}
//删除第i个元素
Status deleteElement(LinkNode *q, int i, int *e){
if(i < 1 || !((*q)->next)) return ERR;
LinkNode p1 = (*q)->next, p2 = (*q);
int n = 1;
while (p1) {
if(n == i)
{
(*e) = p1->data;
p2->next = p1->next;
free(p1);
return OK;
}
n++;
p2 = p1;
p1 = p1->next;
}
return ERR;
}
//头插
Status inserthead(LinkNode *q, int e) {
if(!(*q)) return ERR;
LinkNode p1 = *q;
LinkNode element = (LinkNode)malloc(sizeof(LNode));
element->data = e;
element->next = p1->next;
p1->next = element;
return OK;
}
//尾插
Status inserttail(LinkNode *q, int e) {
if(!(*q)) return ERR;
LinkNode p1 = *q;
while (p1->next) {
p1 = p1->next;
}
LinkNode element = (LinkNode)malloc(sizeof(LNode));
element->data = e;
p1->next = element;
element->next = NULL;
return OK;
}
int main(int argc, const char * argv[]) {
// insert code here...
printf("Hello, World!\n");
int e, i;
LinkNode head = NULL;
//创建
creatLink(&head);
putout(head);
//头插尾插
for (i = 0; i < 10; i+=2) {
if(!inserthead(&head, i)) printf("头插失败");
if(!inserttail(&head, i)) printf("尾插失败");
}
putout(head);
//查找
printf("\n查找\n");
scanf("%d", &i);
while (i) {
if(findElement(head, i, &e)){
printf("第 %d 位置上为 %d\n", i, e);
}else{
printf("输入参数错误!!!\n");
}
scanf("%d", &i);
}
//插入
printf("\n输入位置及在之前插入的数字(输入两个数字)\n");
scanf("%d %d", &i, &e);
while (i) {
if(insertElement(head, i, e)){
putout(head);
}else{
printf("输入参数错误或者空链表\n");
}
getchar();
scanf("%d %d", &i, &e);
}
//删除
printf("\n输入位置删除元素\n");
scanf("%d", &i);
while (i) {
if(deleteElement(&head, i, &e)){
printf("第 %d 位置上为 %d 已经被删除\n", i, e);
putout(head);
}else{
printf("输入参数错误或者空链表\n");
}
getchar();
scanf("%d", &i);
}
return 0;
}
本文来自博客园,作者:赫凯,转载请注明原文链接:https://www.cnblogs.com/heKaiii/p/15491263.html